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/uMain.pas | 1921 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,921 insertions(+), 0 deletions(-)

diff --git a/src/uMain.pas b/src/uMain.pas
new file mode 100644
index 0000000..ec61432
--- /dev/null
+++ b/src/uMain.pas
@@ -0,0 +1,1921 @@
+{------------------------------------------------------------------------------}
+{单元名称:uMain.pas                                                           }
+{模块名称:主进程,负责人机交互界面                                            }
+{模块功能:包含自动检验和手动检验两种模式。                                    }
+{          1.自动检验时,切换自动界面,锁定手动操作,接受扦捡系统指令,反馈结果 }
+{          2.手动检验时,分为检验、分析、校准、设置四个功能模块                }
+{建立日期:2023-10-24                                                          }
+{修改修改:2025-05-23                                                          }
+{版权所有:李良庭 liangtingli@outlook.com                                      }
+{------------------------------------------------------------------------------}
+//2024-07-08 开启主窗体刷新模式,防止PageControl切换时Image闪烁
+//2024-10-14 增加gmmdata数据库,用来存储自动检测和手动检测的所有数据。
+//2024-11-22 临时去掉License授权,供测试用。
+//2025-02-10 增加OpenTabTip调用,通过TabTip.exe手写板完成中文输入。
+//2025-05-07 自动模式下,testThread()线程改为阻塞模式,使用回调函数处理所有指令。
+//2025-05-23 ReadFaultCode()增加一个新的故障码:256-检测无效(出现故障已恢复)。
+
+unit uMain;
+
+interface
+
+{$WARN  UNIT_PLATFORM OFF}
+{$WARN SYMBOL_PLATFORM OFF}
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, jpeg, ExtCtrls, ComCtrls, XPMan, StdCtrls, Buttons, sBitBtn, Math,
+  pngimage, sLabel, iComponent, iVCLComponent, iCustomComponent, StrUtils,
+  iSevenSegmentDisplay, iSevenSegmentClock, iSevenSegmentCharacter, 
+  iSevenSegmentInteger, acImage, iOdometer, sEdit, sListBox,
+  iPlotComponent, iPlot, sComboBox, acPNG, acArcControls,
+  DateUtils, PubUtils, ActuatorLib, ShellApi,
+  // Unit 'FileCtrl' is specific to platform (Windows)
+  FileCtrl;
+
+type
+  TfrmMain = class(TForm)
+    pc: TPageControl;
+    tsAuto: TTabSheet;
+    tsManual: TTabSheet;
+    tsAnalyse: TTabSheet;
+    tsStandard: TTabSheet;
+    tsSetting: TTabSheet;
+    tsSystem: TTabSheet;
+    imgBG: TImage;
+    imgBG1: TImage;
+    btnAuto: TsBitBtn;
+    btnManual: TsBitBtn;
+    sLabel1: TsLabel;
+    imgLogo: TImage;
+    ssClock: TiSevenSegmentClock;
+    ssYear: TiSevenSegmentInteger;
+    iSevenSegmentCharacter1: TiSevenSegmentCharacter;
+    ssMonth: TiSevenSegmentInteger;
+    iSevenSegmentCharacter2: TiSevenSegmentCharacter;
+    ssDay: TiSevenSegmentInteger;
+    sBitBtn1: TsBitBtn;
+    sBitBtn2: TsBitBtn;
+    ssYear1: TiSevenSegmentInteger;
+    iSevenSegmentCharacter3: TiSevenSegmentCharacter;
+    ssMonth1: TiSevenSegmentInteger;
+    iSevenSegmentCharacter4: TiSevenSegmentCharacter;
+    ssDay1: TiSevenSegmentInteger;
+    ssClock1: TiSevenSegmentClock;
+    imgLogo1: TImage;
+    sLabel2: TsLabel;
+    lblAutoInfo: TsLabel;
+    btnTest: TsBitBtn;
+    sBitBtn4: TsBitBtn;
+    sBitBtn5: TsBitBtn;
+    sBitBtn6: TsBitBtn;
+    tsTest: TTabSheet;
+    imgBar1: TImage;
+    imgBar2: TImage;
+    imgBar3: TImage;
+    imgBar4: TImage;
+    btnReturn: TsBitBtn;
+    imgInfo: TsImage;
+    sLabel4: TsLabel;
+    edtMoisture: TsEdit;
+    sLabel5: TsLabel;
+    edtWeightRatio: TsEdit;
+    edtWeight: TsEdit;
+    sLabel10: TsLabel;
+    edtTemp: TsEdit;
+    sLabel11: TsLabel;
+    sLabel12: TsLabel;
+    edtWater: TsEdit;
+    sLabel13: TsLabel;
+    sLabel14: TsLabel;
+    mtManClock: TiOdometer;
+    sLabel15: TsLabel;
+    lbType: TsListBox;
+    btnManTest: TsBitBtn;
+    sLabel16: TsLabel;
+    sLabel17: TsLabel;
+    sLabel18: TsLabel;
+    sLabel19: TsLabel;
+    plDisplay: TPanel;
+    iPlot1: TiPlot;
+    sLabel20: TsLabel;
+    edtTest1: TsEdit;
+    sLabel22: TsLabel;
+    sLabel23: TsLabel;
+    edtAutoCoef1: TsEdit;
+    sLabel24: TsLabel;
+    btnComp: TsBitBtn;
+    btnSave: TsBitBtn;
+    btnSwitchCoef: TsBitBtn;
+    btnVerify1: TsBitBtn;
+    sLabel25: TsLabel;
+    edtMois2: TsEdit;
+    edtAutoCoef2: TsEdit;
+    btnVerify2: TsBitBtn;
+    edtTest2: TsEdit;
+    sLabel26: TsLabel;
+    edtMois3: TsEdit;
+    edtAutoCoef3: TsEdit;
+    btnVerify3: TsBitBtn;
+    edtTest3: TsEdit;
+    sLabel27: TsLabel;
+    edtMois4: TsEdit;
+    edtAutoCoef4: TsEdit;
+    btnVerify4: TsBitBtn;
+    edtTest4: TsEdit;
+    sLabel28: TsLabel;
+    edtMois5: TsEdit;
+    edtAutoCoef5: TsEdit;
+    btnVerify5: TsBitBtn;
+    edtTest5: TsEdit;
+    sLabel29: TsLabel;
+    sLabel30: TsLabel;
+    edtVolume: TsEdit;
+    sLabel31: TsLabel;
+    sLabel32: TsLabel;
+    edtTare: TsEdit;
+    sLabel33: TsLabel;
+    btnSetting: TsBitBtn;
+    edtFreq: TsEdit;
+    edtDecay: TsEdit;
+    sLabel36: TsLabel;
+    sLabel37: TsLabel;
+    sLabel38: TsLabel;
+    edtStartFreq: TsEdit;
+    sLabel39: TsLabel;
+    sLabel40: TsLabel;
+    edtStopFreq: TsEdit;
+    sLabel41: TsLabel;
+    sLabel42: TsLabel;
+    edtStep: TsEdit;
+    sLabel43: TsLabel;
+    sLabel34: TsLabel;
+    sBitBtn7: TsBitBtn;
+    sBitBtn8: TsBitBtn;
+    sBitBtn9: TsBitBtn;
+    lbASK: TsListBox;
+    imgBottom1: TImage;
+    imgBottom2: TImage;
+    imgBottom3: TImage;
+    imgBottom4: TImage;
+    sLabel3: TsLabel;
+    lbType1: TsListBox;
+    edtManCoef1: TsEdit;
+    edtManCoef2: TsEdit;
+    edtManCoef3: TsEdit;
+    edtManCoef4: TsEdit;
+    edtManCoef5: TsEdit;
+    Bevel1: TBevel;
+    imgQuit: TsImage;
+    sBitBtn3: TsBitBtn;
+    imgBarSystem: TImage;
+    sLabel35: TsLabel;
+    sImage1: TsImage;
+    sImage2: TsImage;
+    edtMois1: TsEdit;
+    lblAutoRet: TsLabel;
+    lblAutoRet_error: TsLabel;
+    mtAutoClock: TiOdometer;
+    sLabel44: TsLabel;
+    lblManTest: TsLabel;
+    GroupBox1: TGroupBox;
+    GroupBox2: TGroupBox;
+    sLabel45: TsLabel;
+    edtIP: TsEdit;
+    edtPort: TsEdit;
+    sLabel47: TsLabel;
+    edtBaud: TsEdit;
+    cbSerialPort: TsComboBox;
+    sLabel48: TsLabel;
+    edtParity: TsEdit;
+    sLabel49: TsLabel;
+    edtData_bit: TsEdit;
+    edtStop_bit: TsEdit;
+    btnSaveInfo: TsBitBtn;
+    mtVerifyClock: TiOdometer;
+    lblVerify: TsLabel;
+    sLabel21: TsLabel;
+    Bevel2: TBevel;
+    GroupBox3: TGroupBox;
+    cbAutoRun: TCheckBox;
+    btnReset: TsBitBtn;
+    GroupBox4: TGroupBox;
+    sLabel52: TsLabel;
+    sLabel53: TsLabel;
+    edtTime1: TsEdit;
+    edtTime2: TsEdit;
+    sLabel54: TsLabel;
+    tsWeight: TTabSheet;
+    sBitBtn10: TsBitBtn;
+    Image1: TImage;
+    sLabel55: TsLabel;
+    sBitBtn11: TsBitBtn;
+    sBitBtn12: TsBitBtn;
+    Image2: TImage;
+    sLabel56: TsLabel;
+    sLabel57: TsLabel;
+    sLabel58: TsLabel;
+    sLabel59: TsLabel;
+    edtWTest1: TsEdit;
+    edtWTest2: TsEdit;
+    edtWTest3: TsEdit;
+    btnWeightCoef1: TsBitBtn;
+    btnWeightCoef2: TsBitBtn;
+    btnWeightCoef3: TsBitBtn;
+    sLabel60: TsLabel;
+    edtWeight1: TsEdit;
+    edtWeight2: TsEdit;
+    edtWeight3: TsEdit;
+    Bevel3: TBevel;
+    lblWeightCoef: TsLabel;
+    sLabel63: TsLabel;
+    sBitBtn13: TsBitBtn;
+    GroupBox5: TGroupBox;
+    sLabel61: TsLabel;
+    edtWTare: TsEdit;
+    sLabel62: TsLabel;
+    edtRange: TsEdit;
+    sLabel64: TsLabel;
+    edtWTest: TsEdit;
+    sBitBtn14: TsBitBtn;
+    cbDebug: TCheckBox;
+    GroupBox6: TGroupBox;
+    sLabel65: TsLabel;
+    edtPassword: TsEdit;
+    sLabel66: TsLabel;
+    edtDelay: TsEdit;
+    sLabel67: TsLabel;
+    lblVersion: TsLabel;
+    sBitBtn15: TsBitBtn;
+    tsMaintain: TTabSheet;
+    Image3: TImage;
+    sLabel68: TsLabel;
+    sBitBtn16: TsBitBtn;
+    lblMaintain: TsLabel;
+    Bevel4: TBevel;
+    sBitBtn18: TsBitBtn;
+    sBitBtn19: TsBitBtn;
+    sBitBtn20: TsBitBtn;
+    sBitBtn21: TsBitBtn;
+    sBitBtn22: TsBitBtn;
+    sBitBtn23: TsBitBtn;
+    sBitBtn24: TsBitBtn;
+    sBitBtn25: TsBitBtn;
+    sBitBtn26: TsBitBtn;
+    Bevel5: TBevel;
+    cbTestAutoSave: TCheckBox;
+    sLabel6: TsLabel;
+    edtSampleName: TsEdit;
+    cbAutoSave: TCheckBox;
+    sLabel7: TsLabel;
+    edtPrefix: TEdit;
+    edtDir: TEdit;
+    btnDir: TsBitBtn;
+    btnOSK: TsBitBtn;
+    sBitBtn28: TsBitBtn;
+    sImage4: TsImage;
+    sImage5: TsImage;
+    sBitBtn17: TsBitBtn;
+    sBitBtn27: TsBitBtn;
+    tsIntercept: TTabSheet;
+    Image4: TImage;
+    sLabel8: TsLabel;
+    sBitBtn29: TsBitBtn;
+    Image5: TImage;
+    sLabel9: TsLabel;
+    edtInter1: TsEdit;
+    edtInter2: TsEdit;
+    edtInter3: TsEdit;
+    btnInter1: TsBitBtn;
+    btnInter2: TsBitBtn;
+    btnInter3: TsBitBtn;
+    sLabel46: TsLabel;
+    edtManVal: TsEdit;
+    sLabel69: TsLabel;
+    edtIntercept: TsEdit;
+    btnCopm1: TsBitBtn;
+    btnSave1: TsBitBtn;
+    sLabel70: TsLabel;
+    lbType2: TsListBox;
+    sLabel71: TsLabel;
+    mtInterClock: TiOdometer;
+    Bevel6: TBevel;
+    lblInter: TsLabel;
+    btnAdd: TsBitBtn;
+    btnDel: TsBitBtn;
+    btnModfy: TsBitBtn;
+    sLabel72: TsLabel;
+    sLabel73: TsLabel;
+    sLabel74: TsLabel;
+    sLabel75: TsLabel;
+    sLabel76: TsLabel;
+    sLabel77: TsLabel;
+    GroupBox7: TGroupBox;
+    sLabel50: TsLabel;
+    edtHeartIP: TsEdit;
+    edtHeartPort: TsEdit;
+    btnTareSet: TsBitBtn;
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    procedure FormCreate(Sender: TObject);
+    procedure FormShow(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure btnAutoClick(Sender: TObject);
+    procedure btnTestClick(Sender: TObject);
+    procedure btnReturnClick(Sender: TObject);
+    procedure edtMois1Click(Sender: TObject);
+    procedure imgInfoClick(Sender: TObject);
+    procedure imgQuitClick(Sender: TObject);
+    procedure edtMoistureKeyPress(Sender: TObject; var Key: Char);
+    procedure btnManTestClick(Sender: TObject);
+    procedure btnSettingClick(Sender: TObject);
+    procedure btnVerify1Click(Sender: TObject);
+    procedure btnCompClick(Sender: TObject);
+    procedure lbTypeClick(Sender: TObject);
+    procedure lbType1Click(Sender: TObject);
+    procedure btnSaveInfoClick(Sender: TObject);
+    procedure btnSaveClick(Sender: TObject);
+    procedure btnSwitchCoefClick(Sender: TObject);
+    procedure btnResetClick(Sender: TObject);
+    procedure btnWeightCoef1Click(Sender: TObject);
+    procedure btnTareSetClick(Sender: TObject);
+    procedure sBitBtn11Click(Sender: TObject);
+    procedure sBitBtn12Click(Sender: TObject);
+    procedure sBitBtn13Click(Sender: TObject);
+    procedure sBitBtn10Click(Sender: TObject);
+    procedure sBitBtn14Click(Sender: TObject);
+    procedure sBitBtn3Click(Sender: TObject);
+    procedure sBitBtn15Click(Sender: TObject);
+    procedure sBitBtn18Click(Sender: TObject);
+    procedure sBitBtn19Click(Sender: TObject);
+    procedure btnOSKClick(Sender: TObject);
+    procedure btnDirClick(Sender: TObject);
+    procedure sImage4Click(Sender: TObject);
+    procedure sBitBtn17Click(Sender: TObject);
+    procedure sBitBtn27Click(Sender: TObject);
+    procedure btnInter1Click(Sender: TObject);
+    procedure lbType2Click(Sender: TObject);
+    procedure btnCopm1Click(Sender: TObject);
+    procedure btnSave1Click(Sender: TObject);
+    procedure btnAddClick(Sender: TObject);
+    procedure btnDelClick(Sender: TObject);
+    procedure btnModfyClick(Sender: TObject);
+    procedure sBitBtn28Click(Sender: TObject);
+  protected
+    procedure CreateParams(var Params: TCreateParams); override;
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+    sLoginPwd : String;                              //手动模式返回口令
+    //function  ConnPlc():Integer;                     //连接设备,返回连接状态
+    function  ConnWr():Integer;                      //连接设备,返回连接状态
+    procedure DisconnPlcAndWr();                     //断开设备
+    procedure StartTest(flag:Boolean);               //自动/手动检测
+    procedure ShowCalc(edt:TsEdit; index:Integer);   //动态创建计算器
+    procedure ManLogin_ShowCalc(x,y:Integer);        //手动模式专用口令框
+    procedure SetResetUI(flag:boolean);
+    procedure ShowInput(str: string; mode: Integer=0);
+    procedure GetScreenSize();                       //探测屏幕分辨率类型
+    procedure SetDisplaySize(const typ:Integer);     //设置窗体分辨率
+  end;
+
+type
+  TWordArray = array[0..100] of Word;
+  PWordArray = ^TWordArray;
+
+var
+  frmMain: TfrmMain;
+
+implementation
+
+uses
+  Global, MsgVar, log4me, uDM, uInit, uCalc, uSaveData, uTablet, uInput,
+  mantestThread, verifyThread, grainThread, interceptThread, resetThread,
+  testThread;
+
+var
+  ManTestThread   : TManTestThread;       //手动检测线程
+  VerifyThread    : TVerifyThread;        //校准检测线程
+  GrainThread     : TGrainThread;         //下发粮种线程
+  ResetThread     : TResetThread;         //仪器复位线程
+  InterceptThread : TInterceptThread;     //调整截距线程
+  testThread      : TtestThread;          //自动线程
+
+{$R *.dfm}
+
+//------- 专用函数 -------------------------------------------------------------
+//开启主窗体刷新模式,防止PageControl切换时Image闪烁
+procedure TfrmMain.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+  Params.ExStyle := 33554432; //0x 02 00 00 00
+end;
+
+//------- 自定义函数 -----------------------------------------------------------
+//连接水分仪和PLC设备
+//返回值:0-连接成功
+//        1-PLC连接失败
+//        2-Wr 连接失败
+//        3-PLC和Wr 连接失败
+{function TfrmMain.ConnPlc():Integer;
+begin
+  //连接PLC设备
+  result := StartTcpSlave(502, 'COM1', 115200, 'N', 8, 1, 60, 10, @OnMessageCallBack);
+  if result>=0 then begin
+    lblAutoRet_error.Caption := '';
+    log4info(Format('连接:PLC设备连接成功,返回值=[%d].',[result]));
+  end
+  else begin
+    lblAutoRet_error.Caption := 'PLC连接失败!';
+    log4error(Format('错误:PLC连接失败, 返回值=[%d].',[result]));
+  end;
+end; }
+
+function TfrmMain.ConnWr():Integer;
+begin
+  //连接水分仪设备
+  hWrDev := CreateWrDevice(PChar(WrConn.SerialPort), WrConn.baud, WrConn.parity, WrConn.data_bit, WrConn.stop_bit);
+  //连接设备并显示
+  result := ConnectDevice(hWrDev);
+  if result>=0 then begin
+    lblAutoRet_error.Caption := '';
+    log4info(Format('连接:水分仪设备连接成功,返回值=[%d].',[result]));
+  end
+  else begin
+    lblAutoRet_error.Caption := '水分仪连接失败!';
+    log4error(Format('错误:水分仪连接失败, 返回值=[%d].',[result]));
+  end;
+end;
+
+//断开水分仪和PLC设备
+procedure TfrmMain.DisconnPlcAndWr();
+begin
+  //关闭TCP服务
+  StopTcpSlave;
+  //关闭水分仪
+  Disconnect(hWrDev);
+  DestroyDevice(hWrDev);
+
+  log4info('系统:关闭 扦捡 和水分仪设备!');
+end;
+
+//自定义函数:自动/手动连接设备
+//自动检测时,启动线程AutoTest()
+//手动检测时,销毁线程,等待操作
+//注意:连接设备放在主进程初始化时完成!!!
+procedure TfrmMain.StartTest(flag:Boolean);
+begin
+  //开启自动检测模式
+  if flag then begin
+    //更新信息
+    lblAutoInfo.Caption := '设备已就绪,请等待......';
+    //log4info('模式:切换自动检测模式!');
+    //启动检测
+    if m_TestThread=0 then begin
+      TestThread := TTestThread.Create();
+      m_TestThread := TestThread.Handle;
+      log4info('模式:自动检测模式,启动 TestThread()线程!');
+    end;
+  end
+  //切换到手动模式,销毁线程
+  else begin
+    //log4info('模式:切换手动检测模式!');
+    if m_TestThread<>0 then begin
+      TestThread.Terminate;
+      log4info('模式:手动检测模式,停止 TestThread()线程,准备手动操作!');
+      StopTcpSlave;
+    end;
+  end;
+end;
+
+//自定义函数:探测屏幕分辨率,设置gl_display_size
+//0-最大分辨率,1-1024X768,2-1024X600,3-其他
+procedure TfrmMain.GetScreenSize();
+begin
+  if (Screen.Width>1024)or(Screen.Height>768) then
+    gl_display_type := 0
+  else if (Screen.Width=1024)and(Screen.Height=768) then
+    gl_display_type := 1
+  else if (Screen.Width=1024)and(Screen.Height=600) then
+    gl_display_type := 2
+  else
+    gl_display_type := 3;
+  //打印出来
+  log4info(Format('屏幕:探测屏幕分辨率为[%dX%d],屏幕类型为[%d].',[Screen.Width,Screen.Height,gl_display_type]));
+end;
+
+//自定义函数:自动适配1024X768 和 1024X600 两种分辨率
+procedure TfrmMain.SetDisplaySize(const typ:Integer);
+var
+  ltop,rtop : Integer;
+begin
+  //设置公共偏移量
+  ltop := 100;
+  rtop := 470;
+  if typ=1 then begin
+    //整体尺寸按1024X768
+    frmMain.Width := 1024;
+    frmMain.Height:= 768;
+    //调整边框样式
+    frmMain.BorderStyle := bsNone;
+    //frmMain.WindowState := wsmaximized;
+  end
+  else if typ=2 then begin
+    //整体尺寸按1024X600
+    frmMain.Width := 1024;
+    frmMain.Height:= 600;
+    //调整边框样式
+    frmMain.BorderStyle := bsNone;
+    //frmMain.WindowState := wsmaximized;
+    //适配自动模式页面
+    lblAutoInfo.Top := lblAutoInfo.Top - ltop;
+    lblAutoRet.Top := lblAutoRet.Top - ltop - 20;
+    lblAutoRet_error.Top := lblAutoRet_error.Top - ltop - 20;
+    imgLogo.Top := rtop;
+    sLabel1.Top := rtop;
+    imgInfo.Top := rtop;
+    imgQuit.Top := rtop;
+    //适配手动模式页面
+    imgLogo1.Top := rtop;
+    sLabel2.Top := rtop;
+    sImage1.Top := rtop;
+    sImage2.Top := rtop;
+    //适配系统信息页面
+    GroupBox3.Top := GroupBox3.Top-5;
+    GroupBox3.Height := GroupBox3.Height-10;
+    cbAutoRun.Top := cbAutoRun.Top-5;
+    cbDebug.Top   :=  cbDebug.Top-5;
+    sLabel66.Top  := sLabel66.Top-10;
+    sLabel67.Top  := sLabel67.Top-10;
+    edtDelay.Top  := edtDelay.Top -10;
+
+    GroupBox4.Top := GroupBox4.Top-20;
+    GroupBox4.Height := GroupBox4.Height-10;
+    sLabel52.Top  := sLabel52.Top-10;
+    sLabel53.Top  := sLabel53.Top-10;
+    sLabel54.Top  := sLabel54.Top-10;
+    edtTime1.Top  := edtTime1.Top-10;
+    edtTime2.Top  := edtTime2.Top-10;
+    cbAutoSave.Top:= cbAutoSave.Top-10;
+    edtPrefix.Top := edtPrefix.Top-10;
+    btnOSK.Top := btnOSK.Top-10;
+    sLabel7.Top := sLabel7.Top-10;
+    edtDir.Top := edtDir.Top-10;
+    btnDir.Top := btnDir.Top-10;
+
+    GroupBox2.Top := GroupBox2.Top-5;
+    GroupBox2.Height := GroupBox2.Height-20;
+    GroupBox2.Width  := 355;
+    GroupBox6.Top := GroupBox6.Top-25;
+    GroupBox6.Height := GroupBox6.Height-5;
+    sLabel65.Top     := sLabel65.Top-10;
+    edtPassword.Top  := edtPassword.Top-10;
+    edtPassword.Width:= 166;
+    GroupBox6.Width  := 355;
+    GroupBox7.Width  := 355;
+    edtHeartIp.Width := 141;
+    edtHeartPort.Left:= 250;
+    edtHeartPort.Width:=76;
+    btnSaveInfo.Caption := '保 存';
+    btnSaveInfo.Layout := blGlyphTop;
+    btnSaveInfo.Left := 880;
+    btnSaveInfo.Top  := 230;
+    btnSaveInfo.Height:= 90;
+    btnSaveInfo.Width := 110;
+    btnReset.Caption := '复 位';
+    btnReset.Layout := blGlyphTop;
+    btnReset.Left := 880;
+    btnReset.Top  := 380;
+    btnReset.Height:= 90;
+    btnReset.Width := 110;
+
+    //适配手动检测界面
+    sLabel14.Top:= sLabel14.Top- 10;
+    mtManClock.Top:=mtManClock.Top-10;
+    lblManTest.Top:=lblManTest.Top-10;
+    Bevel1.Top := Bevel1.Top - 30;
+    sLabel4.Top:= sLabel4.Top- 50;
+    sLabel5.Top:= sLabel5.Top- 50;
+    edtMoisture.Top := edtMoisture.Top-50;
+    sLabel15.Top:= sLabel15.Top- 55;
+    sLabel10.Top:= sLabel10.Top- 70;
+    sLabel11.Top:= sLabel11.Top- 70;
+    edtTemp.Top := edtTemp.Top - 70;
+    sLabel12.Top:= sLabel12.Top- 80;
+    sLabel13.Top:= sLabel13.Top- 80;
+    edtWater.Top := edtWater.Top-80;
+    cbTestAutoSave.Top := cbTestAutoSave.Top-95;
+    sLabel6.Top:= sLabel6.Top- 105;
+    edtSampleName.Top := edtSampleName.Top-105;
+    sBitBtn28.Top := sBitBtn28.Top-105;
+    lbType.Top := lbType.Top-70;
+    lbType.Height := lbType.Height-36;
+    lbType.Width  := lbType.Width +30;
+    btnManTest.Top:= btnManTest.Top-130;
+    btnManTest.Height:= btnManTest.Height-10;
+
+    //适配仪器维护界面
+    lblMaintain.Top := lblMaintain.Top-20;
+    Bevel4.Top := Bevel4.Top-40;
+    sBitBtn17.Top := sBitBtn17.Top-50;
+    sBitBtn18.Top := sBitBtn18.Top-50;
+    Bevel5.Top := Bevel5.Top-60;
+    sBitBtn19.Top := sBitBtn19.Top-70;
+    sBitBtn20.Top := sBitBtn20.Top-70;
+    sBitBtn21.Top := sBitBtn21.Top-70;
+    sBitBtn22.Top := sBitBtn22.Top-70;
+    sBitBtn23.Top := sBitBtn23.Top-80;
+    sBitBtn24.Top := sBitBtn24.Top-80;
+    sBitBtn25.Top := sBitBtn25.Top-80;
+    sBitBtn26.Top := sBitBtn26.Top-80;
+
+    //适配数据分析界面
+    iPlot1.Height := iPlot1.Height-180;
+
+    //适配仪器校准界面
+    sLabel21.Top:= sLabel21.Top- 10;
+    mtVerifyClock.Top:=mtVerifyClock.Top-10;
+    lblVerify.Top:=lblVerify.Top-10;
+    Bevel2.Top := Bevel2.Top - 20;
+    sLabel25.Top := sLabel25.Top - 35;
+    sLabel26.Top := sLabel26.Top - 35;
+    sLabel27.Top := sLabel27.Top - 35;
+    sLabel28.Top := sLabel28.Top - 35;
+    sLabel29.Top := sLabel29.Top - 35;
+    sLabel20.Top := sLabel20.Top - 40;
+    edtTest1.Top := edtTest1.Top - 40;
+    edtTest2.Top := edtTest2.Top - 40;
+    edtTest3.Top := edtTest3.Top - 40;
+    edtTest4.Top := edtTest4.Top - 40;
+    edtTest5.Top := edtTest5.Top - 40;
+    btnVerify1.Top := btnVerify1.Top - 50;
+    btnVerify2.Top := btnVerify2.Top - 50;
+    btnVerify3.Top := btnVerify3.Top - 50;
+    btnVerify4.Top := btnVerify4.Top - 50;
+    btnVerify5.Top := btnVerify5.Top - 50;
+    sLabel22.Top := sLabel22.Top - 100;
+    edtMois1.Top := edtMois1.Top - 100;
+    edtMois2.Top := edtMois2.Top - 100;
+    edtMois3.Top := edtMois3.Top - 100;
+    edtMois4.Top := edtMois4.Top - 100;
+    edtMois5.Top := edtMois5.Top - 100;
+    sLabel23.Top := sLabel23.Top - 110;
+    edtAutoCoef1.Top := edtAutoCoef1.Top - 110;
+    edtAutoCoef2.Top := edtAutoCoef2.Top - 110;
+    edtAutoCoef3.Top := edtAutoCoef3.Top - 110;
+    edtAutoCoef4.Top := edtAutoCoef4.Top - 110;
+    edtAutoCoef5.Top := edtAutoCoef5.Top - 110;
+    sLabel24.Top := sLabel24.Top - 120;
+    edtManCoef1.Top := edtManCoef1.Top - 120;
+    edtManCoef2.Top := edtManCoef2.Top - 120;
+    edtManCoef3.Top := edtManCoef3.Top - 120;
+    edtManCoef4.Top := edtManCoef4.Top - 120;
+    edtManCoef5.Top := edtManCoef5.Top - 120;
+    sLabel3.Top := sLabel3.Top - 35;
+    lbType1.Top := lbType1.Top - 40;
+    lbType1.Height := lbType1.Height - 40;
+    lbType1.Width  := lbType1.Width + 10;
+    btnSwitchCoef.Top := btnSwitchCoef.Top -95;
+    btnSwitchCoef.Height:= btnSwitchCoef.Height-10;
+    btnComp.Top   := btnComp.Top - 130;
+    btnComp.Height:= btnComp.Height-10;
+    btnSave.Top   := btnSave.Top - 130;
+    btnSave.Height:= btnSave.Height-10;
+
+    //适配重量校准界面
+    sLabel63.Top := sLabel63.Top- 10;
+    lblWeightCoef.Top := lblWeightCoef.Top- 10;
+    Bevel3.Top := Bevel3.Top - 20;
+    sLabel57.Top := sLabel57.Top- 35;
+    sLabel58.Top := sLabel58.Top- 35;
+    sLabel59.Top := sLabel59.Top- 35;
+    sLabel56.Top := sLabel56.Top- 40;
+    edtWTest1.Top := edtWTest1.Top-40;
+    edtWTest2.Top := edtWTest2.Top-40;
+    edtWTest3.Top := edtWTest3.Top-40;
+    sLabel60.Top := sLabel60.Top- 50;
+    edtWeight1.Top := edtWeight1.Top-50;
+    edtWeight2.Top := edtWeight2.Top-50;
+    edtWeight3.Top := edtWeight3.Top-50;
+    btnWeightCoef1.Top := btnWeightCoef1.Top-60;
+    btnWeightCoef2.Top := btnWeightCoef2.Top-60;
+    btnWeightCoef3.Top := btnWeightCoef3.Top-60;
+    sLabel64.Top := sLabel64.Top-100;
+    edtWTest.Top := edtWTest.Top-100;
+    sBitBtn14.Top := sBitBtn14.Top-100;
+    GroupBox5.Top := GroupBox5.Top- 35;
+    btnTareSet.Top:= btnTareSet.Top-40;
+    sBitBtn11.Top   := sBitBtn11.Top - 130;
+    sBitBtn11.Height:= sBitBtn11.Height-10;
+    sBitBtn12.Top   := sBitBtn12.Top - 130;
+    sBitBtn12.Height:= sBitBtn12.Height-10;
+
+    //适配调整截距界面
+    sLabel71.Top := sLabel71.Top - 10;
+    mtInterClock.Top := mtInterClock.Top - 10;
+    lblInter.Top := lblInter.Top - 10;
+    Bevel6.Top := Bevel6.Top - 20;
+    Label1.Top := Label1.Top - 20;
+    Label2.Top := Label2.Top - 20;
+    Label3.Top := Label3.Top - 20;
+    sLabel9.Top := sLabel9.Top - 20;
+    edtInter1.Top := edtInter1.Top - 20;
+    edtInter2.Top := edtInter2.Top - 20;
+    edtInter3.Top := edtInter3.Top - 20;
+    btnInter1.Top := btnInter1.Top - 30;
+    btnInter2.Top := btnInter2.Top - 30;
+    btnInter3.Top := btnInter3.Top - 30;
+    sLabel46.Top := sLabel46.Top - 90;
+    edtManVal.Top := edtManVal.Top - 90;
+    sLabel69.Top := sLabel69.Top - 100;
+    edtIntercept.Top := edtIntercept.Top - 100;
+
+    sLabel70.Top := sLabel70.Top - 20;
+    lbType2.Top := lbType2.Top - 20;
+    lbType2.Height := lbType2.Height - 70;
+    btnAdd.Top := btnAdd.Top - 90;
+    btnModfy.Top := btnModfy.Top - 90;
+    btnDel.Top := btnDel.Top - 90;
+
+    btnCopm1.Top   := btnCopm1.Top - 130;
+    btnCopm1.Height:= btnCopm1.Height-10;
+    btnSave1.Top   := btnSave1.Top - 130;
+    btnSave1.Height:= btnSave1.Height-10;
+
+    //适配参数设置界面
+    sLabel30.Top := sLabel30.Top - 40;
+    sLabel31.Top := sLabel31.Top - 40;
+    edtVolume.Top := edtVolume.Top - 40;
+    sLabel38.Top := sLabel38.Top - 40;
+    sLabel39.Top := sLabel39.Top - 40;
+    edtStartFreq.Top := edtStartFreq.Top - 40;
+    sLabel32.Top := sLabel32.Top - 50;
+    sLabel33.Top := sLabel33.Top - 50;
+    edtTare.Top := edtTare.Top - 50;
+    sLabel41.Top := sLabel41.Top - 50;
+    sLabel40.Top := sLabel40.Top - 50;
+    edtStopFreq.Top := edtStopFreq.Top - 50;
+    sLabel37.Top := sLabel37.Top - 60;
+    edtFreq.Top := edtFreq.Top - 60;
+    sLabel42.Top := sLabel42.Top - 60;
+    sLabel43.Top := sLabel43.Top - 60;
+    edtStep.Top := edtStep.Top - 60;
+    sLabel36.Top := sLabel36.Top - 70;
+    edtDecay.Top := edtDecay.Top - 70;
+    sLabel34.Top := sLabel34.Top - 80;
+    lbASK.Top := lbASK.Top - 80;
+    btnSetting.Top   := btnSetting.Top - 130;
+    btnSetting.Height:= btnSetting.Height-10;
+  end;
+end;
+//------- 界面初始化 -----------------------------------------------------------
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+  InitGlobal();        //初始化全局变量
+  InitSystemDir();     //建立系统文件夹
+  InitDatas();         //初始化采集数据结构
+  InitConfig();        //创建config参数数据库
+  InitConn();          //创建conn通讯数据库
+  InitGrain();         //创建grain粮种数据库
+  InitTestDB();        //创建test存储数据库
+  InitWeight();        //创建weight重量校准数据
+  InitManager();       //创建manager管理口令数据库
+  LoadParam();         //装载config、conn、grain、wiehgit、manager参数
+  LoadSystemInfo();    //装载system参数
+
+  //获取软件版权信息
+  GetVersionInfo(Application.ExeName);
+  //探测屏幕分辨率
+  GetScreenSize();
+  //调整人机界面最大化
+  SetDisplaySize(2);
+end;
+
+procedure TfrmMain.FormShow(Sender: TObject);
+var
+  i : Integer;
+begin
+  //根据启动延时参数,推迟启动时间
+  Sleep(SysConfig.delay * 1000);
+  
+  //初始化pc页面,默认显示扫描页面
+  for i := 0 to pc.PageCount - 1 do
+    pc.Pages[i].TabVisible := False;
+  pc.ActivePage := tsAuto;
+  //加载授权检查模块
+  //测试版本,注释软件授权功能
+  //RegCheckMode();
+
+  //加载参数到界面
+  LoadOptions();
+  
+  //开启自动模式
+  ConnWr();
+  StartTest(true);
+end;
+
+procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  //销毁设备
+  DisconnPlcAndWr();
+end;
+
+//------- 切换自动--手动模式----------------------------------------------------
+//切换自动模式
+procedure TfrmMain.btnAutoClick(Sender: TObject);
+begin
+  case TsBitBtn(Sender).Tag of
+    1:begin//自动模式
+        pc.ActivePage := tsAuto;
+        StartTest(true);
+      end;
+    2:begin//手动模式
+        //先验证口令,正确才允许切换
+        if gl_display_type=2 then
+          ManLogin_ShowCalc(300,150)
+        else
+          ManLogin_ShowCalc(300,250);
+        //销毁自动检测线程
+        if sLoginPwd=SysConfig.password then begin
+          pc.ActivePage := tsManual;
+          StartTest(false);
+        end;
+      end;
+  end;
+end;
+
+//手动模式导航按钮
+procedure TfrmMain.btnTestClick(Sender: TObject);
+begin
+  case TsBitBtn(Sender).Tag of
+    3:begin//检测
+        pc.ActivePage := tsTest;
+        //加载粮种列表
+        queryGrainlistSql(t_Grain, lbType);
+      end;
+    4:begin//分析
+        pc.ActivePage := tsAnalyse;
+      end;
+    5:begin//校准
+        pc.ActivePage := tsStandard;
+        //加载粮种列表
+        queryGrainlistSql(t_Grain, lbType1);
+      end;
+    6:begin//设置
+        pc.ActivePage := tsSetting;
+      end;
+  end;
+end;
+
+//返回手动模式--首页
+procedure TfrmMain.btnReturnClick(Sender: TObject);
+begin
+  pc.ActivePage := tsManual;
+end;
+
+//返回自动模式--首页
+procedure TfrmMain.sBitBtn3Click(Sender: TObject);
+begin
+  pc.ActivePage := tsManual;
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType);
+end;
+
+//切换到系统页面
+procedure TfrmMain.imgInfoClick(Sender: TObject);
+begin
+  //先验证口令,正确才允许进入
+  if gl_display_type=2 then
+    ManLogin_ShowCalc(300,150)
+  else
+    ManLogin_ShowCalc(300,250);
+  //销毁自动检测线程
+  if sLoginPwd=SysConfig.password then
+    pc.ActivePage := tsSystem;
+end;
+
+//退出上位机
+procedure TfrmMain.imgQuitClick(Sender: TObject);
+begin
+  close();
+end;
+
+//------- 校准功能 -------------------------------------------------------------
+//从仪器校准跳转到重量校准
+procedure TfrmMain.sBitBtn13Click(Sender: TObject);
+begin
+  pc.ActivePage := tsWeight;
+  //更新当前公式
+  if Wg.b>0 then
+    lblWeightCoef.Caption := Format('校准公式 Y = %.4fX + %.4f,误差±%.4f !', [Wg.k,Wg.b,Wg.range])
+  else
+    lblWeightCoef.Caption := Format('校准公式 Y = %.4fX - %.4f,误差±%.4f !', [Wg.k,Abs(Wg.b),Wg.range]);
+  //更新界面
+  edtWTare.Text := FloatToStr(Wg.tare);
+  edtRange.Text := FloatToStr(Wg.range);
+end;
+
+//计算截距
+procedure TfrmMain.sBitBtn27Click(Sender: TObject);
+begin
+  pc.ActivePage := tsIntercept;
+  //加载粮种列表
+  //queryGrainlistSql(t_Grain, lbType2, 0);
+  queryGrainlistSql(t_Grain, lbType2);
+end;
+
+//返回仪器校准
+procedure TfrmMain.sBitBtn10Click(Sender: TObject);
+begin
+  pc.ActivePage := tsStandard;
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType1);
+  sLabel3.Caption := '粮食种类';
+end;
+
+//------- Edit输入区 -----------------------------------------------------------
+//公共函数:动态创建计算器
+procedure TfrmMain.ShowCalc(edt:TsEdit; index:Integer);
+var
+  p : TPoint;
+begin
+  frmCalc := TfrmCalc.Create(Application);  //创建动态窗体
+  frmCalc.strParam := edt.Text;             //传入修改值
+  p := GetCurrMsgPos(index);                //计算输入框坐标
+  frmCalc.Left := p.x;                      //修改计算器坐标
+  frmCalc.Top  := p.y;
+  frmCalc.ShowModal;                        //模态窗口显示calc
+end;
+
+//手动登录专用输入框
+procedure TfrmMain.ManLogin_ShowCalc(x,y:Integer);
+begin
+  frmCalc := TfrmCalc.Create(Application);  //创建动态窗体
+  frmCalc.strParam := '';                   //传入修改值
+  frmCalc.Left := frmMain.Left + x;         //修改计算器坐标
+  frmCalc.Top  := frmMain.Top + y;
+  glCurrFocus := 0;                         //焦点编号-->frmMain.sLoginPwd
+  frmCalc.ShowModal;                        //模态窗口显示calc
+end;
+
+//确定输入Edit编号,定位键盘显示位置,弹出小键盘
+procedure TfrmMain.edtMois1Click(Sender: TObject);
+begin
+  case TsEdit(Sender).Tag of
+    1:begin
+      glCurrFocus := 1;                //设置Edit焦点编号
+      ShowCalc(edtMois1, glCurrFocus); //显示小键盘
+    end;
+    2:begin
+      glCurrFocus := 2;
+      ShowCalc(edtMois2, glCurrFocus);
+    end;
+    3:begin
+      glCurrFocus := 3;
+      ShowCalc(edtMois3, glCurrFocus);
+    end;
+    4:begin
+      glCurrFocus := 4;
+      ShowCalc(edtMois4, glCurrFocus);
+    end;
+    5:begin
+      glCurrFocus := 5;
+      ShowCalc(edtMois5, glCurrFocus);
+    end;
+    6:begin
+      glCurrFocus := 6;
+      ShowCalc(edtManCoef1, glCurrFocus);
+    end;
+    7:begin
+      glCurrFocus := 7;
+      ShowCalc(edtManCoef2, glCurrFocus);
+    end;
+    8:begin
+      glCurrFocus := 8;
+      ShowCalc(edtManCoef3, glCurrFocus);
+    end;
+    9:begin
+      glCurrFocus := 9;
+      ShowCalc(edtManCoef4, glCurrFocus);
+    end;
+    10:begin
+      glCurrFocus := 10;
+      ShowCalc(edtManCoef5, glCurrFocus);
+    end;
+    11:begin
+      glCurrFocus := 11;
+      ShowCalc(edtIp, glCurrFocus);
+    end;
+    12:begin
+      glCurrFocus := 12;
+      ShowCalc(edtPort, glCurrFocus);
+    end;
+    13:begin
+      glCurrFocus := 13;
+      ShowCalc(edtTime1, glCurrFocus);
+    end;
+    14:begin
+      glCurrFocus := 14;
+      ShowCalc(edtTime2, glCurrFocus);
+    end;
+    15:begin
+      glCurrFocus := 15;
+      ShowCalc(edtWeight1, glCurrFocus);
+    end;
+    16:begin
+      glCurrFocus := 16;
+      ShowCalc(edtWeight2, glCurrFocus);
+    end;
+    17:begin
+      glCurrFocus := 17;
+      ShowCalc(edtWeight3, glCurrFocus);
+    end;
+    18:begin
+      glCurrFocus := 18;
+      ShowCalc(edtWTare, glCurrFocus);
+    end;
+    19:begin
+      glCurrFocus := 19;
+      ShowCalc(edtRange, glCurrFocus);
+    end;
+    20:begin
+      glCurrFocus := 20;
+      ShowCalc(edtVolume, glCurrFocus);
+    end;
+    21:begin
+      glCurrFocus := 21;
+      ShowCalc(edtTare, glCurrFocus);
+    end;
+    22:begin
+      glCurrFocus := 22;
+      ShowCalc(edtDelay, glCurrFocus);
+    end;
+    23:begin
+      glCurrFocus := 23;
+      ShowCalc(edtPassword, glCurrFocus);
+    end;
+    24:begin//调整截距-人工含水率
+      glCurrFocus := 24;               //设置Edit焦点编号
+      ShowCalc(edtManVal, glCurrFocus);//显示小键盘
+    end;
+    25:begin//调整截距-手动输入截距
+      glCurrFocus := 25;
+      ShowCalc(edtIntercept, glCurrFocus);
+    end;
+    26:begin//调整心跳ip
+      glCurrFocus := 26;
+      ShowCalc(edtHeartIp, glCurrFocus);
+    end;
+    27:begin//调整心跳port
+      glCurrFocus := 27;
+      ShowCalc(edtHeartPort, glCurrFocus);
+    end;
+  end;
+end;
+
+//其他Edit设置只读,防止输入数值
+procedure TfrmMain.edtMoistureKeyPress(Sender: TObject; var Key: Char);
+begin
+  Key := Chr(0);
+end;
+
+//------- 手动检测 --------------------------------------
+//手动--检测,选择粮种
+procedure TfrmMain.lbTypeClick(Sender: TObject);
+var
+  ss : string;
+begin
+  //容错处理
+  if lbType.ItemIndex<0 then exit;
+
+  //设置线程标志
+  s_Grain := 1;  //1-手动检测;2-手动校准;3-调整截距
+
+  //检查是否在手动测试中
+  if m_ManTestThread<>0 then begin
+    MessageBox(handle,'提示:当前正在进行含水率检测,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType.ItemIndex := glCurrIndex;
+    exit;
+  end;
+
+  //检查线程是否启动
+  if m_GrainThread=0 then begin
+    glCurrIndex := lbType.ItemIndex;
+    ss := lbType.Items[glCurrIndex];
+    //加载粮种校准系数
+    Grain := queryGrainSql(t_Grain, ss);
+    //初始化界面
+    edtMoisture.Clear;
+    edtWeightRatio.Clear;
+    edtWeight.Clear;
+    edtTemp.Clear;
+    edtWater.Clear;
+    //启动下发粮种线程
+    GrainThread := TGrainThread.Create();
+    m_GrainThread := GrainThread.Handle;
+  end
+  else begin
+    //如果线程未结束,不能强行终止,仅提示!!!
+    //GrainThread.Terminate;
+    MessageBox(handle,'提示:当前粮种下发指令尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType.ItemIndex := glCurrIndex;
+  end;
+end;
+
+//手动检测含水率
+procedure TfrmMain.btnManTestClick(Sender: TObject);
+begin
+  //先保存临时参数
+  smp.flag := cbTestAutoSave.Checked;
+  smp.info := edtSampleName.Text;
+  cbAutoSave.Checked := cbTestAutoSave.Checked;//同步更新系统界面
+  if FileExists(glConn_db) then begin
+    //增加数据存储参数
+    updateConfigSql(t_Conn,'AutoSave',BoolToString(smp.flag));
+    updateConfigSql(t_Conn,'SampleName',  smp.info);
+    //记录日志
+    //log4info(Format('提示:手动检测时,更新 %s-样本存储参数.',[t_Conn]));
+  end;
+
+  //启动手动检测线程,优化界面显示
+  if (m_ManTestThread=0)and(m_VerifyThread=0)and(m_InterceptThread=0) then begin
+    //初始化界面
+    lblManTest.Caption := '开始含水率检测.';
+    edtMoisture.Clear;
+    edtWeightRatio.Clear;
+    edtWeight.Clear;
+    edtTemp.Clear;
+    edtWater.Clear;
+    //启动手动检测线程
+    ManTestThread := TManTestThread.Create();
+    m_ManTestThread := ManTestThread.Handle;
+  end
+  else begin
+    if m_ManTestThread<>0 then
+      MessageBox(handle,'提示:当前检测过程尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    if m_VerifyThread<>0 then
+      MessageBox(handle,'提示:手动校准过程尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    if m_InterceptThread<>0 then
+      MessageBox(handle,'提示:调整截距过程尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+  end;
+end;
+
+//------- 手动校准 ------------------------------------------------------
+//仪器校准--选择粮种
+procedure TfrmMain.lbType1Click(Sender: TObject);
+var
+  ss : string;
+begin
+  //容错处理
+  if lbType1.ItemIndex<0 then exit;
+
+  //设置线程标志
+  s_Grain := 2;  //1-手动检测;2-手动校准;3-调整截距
+
+  //检查是否在手动测试中
+  if m_VerifyThread<>0 then begin
+    MessageBox(handle,'提示:当前正在进行校准检测,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType1.ItemIndex := glCurrIndex;
+    exit;
+  end;
+
+  //检查线程是否启动
+  if m_GrainThread=0 then begin
+    //返回值
+    glCurrIndex := lbType1.ItemIndex;
+    ss := lbType1.Items[glCurrIndex];
+    //加载粮种校准系数
+    Grain := queryGrainSql(t_Grain, ss);
+    //启动下发粮种线程
+    GrainThread := TGrainThread.Create();
+    m_GrainThread := GrainThread.Handle;
+  end
+  else begin
+    //如果线程未结束,仅提示!!!
+    MessageBox(handle,'提示:当前粮种下发指令尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType1.ItemIndex := glCurrIndex;
+  end;
+end;
+
+//手动检测一组电平
+procedure TfrmMain.btnVerify1Click(Sender: TObject);
+begin
+   glBtnTag := TsBitBtn(Sender).Tag;
+
+  //启动校准线程,优化界面显示
+  if (m_VerifyThread=0)and(m_ManTestThread=0)and(m_InterceptThread=0) then begin
+    //初始化界面
+    lblVerify.Caption := '开始校准检测.';
+    //启动手动检测线程
+    VerifyThread := TVerifyThread.Create();
+    m_VerifyThread := VerifyThread.Handle;
+  end
+  else begin
+    if m_VerifyThread<>0 then
+      lblVerify.Caption := '当前校准过程尚未结束,请稍后再试!';
+    if m_ManTestThread<>0 then
+      lblVerify.Caption := '手动检测过程尚未结束,请稍后再试!';
+    if m_InterceptThread<>0 then
+      lblInter.Caption := '调整截距过程尚未结束,请稍后再试!';
+  end;
+end;
+
+//手动计算校准系数
+procedure TfrmMain.btnCompClick(Sender: TObject);
+var
+  vccval,inputval,coef : array [0..4] of double;
+begin
+  //填充计算条件
+  vccval[0] := StrToFloat(edtTest1.Text);
+  vccval[1] := StrToFloat(edtTest2.Text);
+  vccval[2] := StrToFloat(edtTest3.Text);
+  vccval[3] := StrToFloat(edtTest4.Text);
+  vccval[4] := StrToFloat(edtTest5.Text);
+  inputval[0] := StrToFloat(edtMois1.Text);
+  inputval[1] := StrToFloat(edtMois2.Text);
+  inputval[2] := StrToFloat(edtMois3.Text);
+  inputval[3] := StrToFloat(edtMois4.Text);
+  inputval[4] := StrToFloat(edtMois5.Text);
+  //开始计算
+  //Linearize(@vccval, @inputval, @coef, 3, 5);
+  PolyNomialFit(@vccval, @inputval, @coef, 3, 5);
+  //输出结果
+  Grain.Coef[0] := FloatToStr(coef[0]);
+  Grain.Coef[1] := FloatToStr(coef[1]);
+  Grain.Coef[2] := FloatToStr(coef[2]);
+  Grain.Coef[3] := FloatToStr(coef[3]);
+  Grain.Coef[4] := FloatToStr(coef[4]);
+  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];
+  //界面显示计算结束
+  lblVerify.Caption := '完成仪器校准,结果输出至[自动校准系数].';
+end;
+
+//仪器校准--切换系数
+procedure TfrmMain.btnSwitchCoefClick(Sender: TObject);
+var
+  s1,s2,s3,s4,s5 : string;
+begin
+  s1 := edtManCoef1.Text;
+  s2 := edtManCoef2.Text;
+  s3 := edtManCoef3.Text;
+  s4 := edtManCoef4.Text;
+  s5 := edtManCoef5.Text;
+  edtManCoef1.Text := edtAutoCoef1.Text;
+  edtManCoef2.Text := edtAutoCoef2.Text;
+  edtManCoef3.Text := edtAutoCoef3.Text;
+  edtManCoef4.Text := edtAutoCoef4.Text;
+  edtManCoef5.Text := edtAutoCoef5.Text;
+  edtAutoCoef1.Text := s1;
+  edtAutoCoef2.Text := s2;
+  edtAutoCoef3.Text := s3;
+  edtAutoCoef4.Text := s4;
+  edtAutoCoef5.Text := s5;
+end;
+
+//仪器校准--保存校准系数
+procedure TfrmMain.btnSaveClick(Sender: TObject);
+begin
+  //更新Grain数据结构
+  Grain.Coef[0] := edtAutoCoef1.Text;
+  Grain.Coef[1] := edtAutoCoef2.Text;
+  Grain.Coef[2] := edtAutoCoef3.Text;
+  Grain.Coef[3] := edtAutoCoef4.Text;
+  Grain.Coef[4] := edtAutoCoef5.Text;
+
+  //保存系数
+  SaveVerifyParam();
+  //记录日志并弹框提示
+  lblVerify.Caption := Format('保存新的校准系数到 [%s]粮种信息!',[Grain.Name]);
+  log4Info(Format('粮种:保存[%s]粮种信息, 代码[%d], 校准系数[%s,%s,%s,%s,%s]',
+                  [Grain.Name,
+                   Grain.Code,
+                   Grain.Coef[0],
+                   Grain.Coef[1],
+                   Grain.Coef[2],
+                   Grain.Coef[3],
+                   Grain.Coef[4]]));
+end;
+
+//------- 调整截距功能模块 -----------------------------------------------------
+//专用输入框
+procedure TfrmMain.ShowInput(str: string; mode: Integer=0);
+begin
+  frmInput := TfrmInput.Create(Application);  //创建动态窗体
+  frmInput.thMode := mode;                    //输入框模式:0-默认输入框,1-粮种大类选择框
+  frmInput.strParam := str;                   //传入修改值
+  frmInput.Left := frmMain.Left+ 300;         //修改计算器坐标
+  if gl_display_type=2 then
+    frmInput.Top  := frmMain.Top + 150
+  else
+    frmInput.Top  := frmMain.Top + 50;
+  frmInput.ShowModal;                         //模态窗口显示calc
+end;
+
+//调整截距--选择粮种
+procedure TfrmMain.lbType2Click(Sender: TObject);
+var
+  ss : string;
+begin
+  //容错处理
+  if lbType2.ItemIndex<0 then exit;
+
+  //设置线程标志
+  s_Grain := 3;  //1-手动检测;2-手动校准;3-调整截距
+
+  //检查是否在手动测试中
+  if m_InterceptThread<>0 then begin
+    MessageBox(handle,'提示:当前正在调整截距,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType2.ItemIndex := glCurrIndex;
+    exit;
+  end;
+
+  //检查线程是否启动
+  if m_GrainThread=0 then begin
+    //返回值
+    glCurrIndex := lbType2.ItemIndex;
+    ss := lbType2.Items[glCurrIndex];
+    //加载粮种校准系数
+    Grain := queryGrainSql(t_Grain, ss);
+    edtIntercept.Text := Grain.Intercept;
+    //启动下发粮种线程
+    GrainThread := TGrainThread.Create();
+    m_GrainThread := GrainThread.Handle;
+  end
+  else begin
+    //如果线程未结束,仅提示!!!
+    MessageBox(handle,'提示:当前粮种下发指令尚未结束,请稍后再试!','警告对话框',MB_OK+MB_ICONWARNING);
+    lbType2.ItemIndex := glCurrIndex;
+  end;
+end;
+
+//调整截距--检测含水率
+procedure TfrmMain.btnInter1Click(Sender: TObject);
+begin
+  glBtnTag1 := TsBitBtn(Sender).Tag;
+
+  //启动调整截距线程
+  if (m_VerifyThread=0)and(m_ManTestThread=0)and(m_InterceptThread=0) then begin
+    //初始化界面
+    lblInter.Caption := Format('开始检测第 [%d] 组水分.', [glBtnTag1]);
+    //启动线程
+    InterceptThread := TInterceptThread.Create();
+    m_InterceptThread := InterceptThread.Handle;
+  end
+  else begin
+    if m_VerifyThread<>0 then
+      lblVerify.Caption := '当前校准过程尚未结束,请稍后再试!';
+    if m_ManTestThread<>0 then
+      lblVerify.Caption := '手动检测过程尚未结束,请稍后再试!';
+    if m_InterceptThread<>0 then
+      lblInter.Caption := '调整截距过程尚未结束,请稍后再试!';
+  end;
+end;
+
+//根据三组检测值+人工输入含水率,计算当前截距
+//计算公式:Intercept = RealMois - (M1+M2+M3)/3
+procedure TfrmMain.btnCopm1Click(Sender: TObject);
+var
+  moisval : array [0..2] of double;
+  interval : double;
+begin
+  //填充计算条件
+  moisval[0] := StrToFloat(edtInter1.Text);
+  moisval[1] := StrToFloat(edtInter2.Text);
+  moisval[2] := StrToFloat(edtInter3.Text);
+
+  //开始计算,结果保留两位小数
+  interval := RoundTo(StrToFloatDef(edtManVal.Text, 0) - ((moisval[0]+moisval[1]+moisval[2])/3), -2);
+  //输出结果
+  edtIntercept.Text := FloatToStr(interval);
+  //界面显示计算结束
+  lblInter.Caption := '完成截距评估,结果为['+edtIntercept.Text+'%].';
+end;
+
+//保存当前截距
+procedure TfrmMain.btnSave1Click(Sender: TObject);
+begin
+  //保存系数
+  Grain.Intercept := edtIntercept.Text;
+  SaveInterceptParam(edtIntercept.Text);
+  //记录日志并弹框提示
+  lblInter.Caption := Format('提示:保存截距参数到 [%s] 粮种信息!',[Grain.Name]);
+  log4Info(Format('粮种:保存 [%s] 粮种信息, 代码-[%d], 截距-[%s]',
+                  [Grain.Name, Grain.Code, Grain.Intercept]));
+end;
+
+//新增粮种
+procedure TfrmMain.btnAddClick(Sender: TObject);
+//var
+//  nam : string;
+begin
+  //启动手写输入框
+  {frmTablet := TfrmTablet.Create(Application);  //创建动态窗体
+  frmTablet.ShowModal;                          //模态窗口显示Tablet
+  nam := glInkOutput;
+
+  //判断是否重名,是否未改名
+  if Trim(nam)='' then exit;
+  if queryGrainNumSql(t_Grain, nam)>0 then begin
+    MessageBox(handle,'错误:您新增的粮种重名,请检查后重新提交!','错误对话框',MB_OK+MB_ICONERROR);
+    exit;
+  end;
+
+  //新增粮种
+  AddGrainRecord(Trim(nam));
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType2); }
+
+  {//创建输入对话框
+  if InputQuery('新增对话框', '请输入粮种名称:.', nam) then begin
+    if Trim(nam)<>'' then begin
+      //新增粮种
+      AddGrainRecord(Trim(nam));
+      //加载粮种列表
+      queryGrainlistSql(t_Grain, lbType2);
+    end;
+  end;}
+
+  //打开触控板
+  ShellExecute(0, nil, 'OpenTabTip', nil, nil, SW_SHOWNORMAL);
+  //创建输入对话框
+  ShowInput('', 1);
+  if glInput<>'' then begin
+    //判断是否重名,是否未改名
+    if queryGrainNumSql(t_Grain, glInput, GrainType_rec.Code)>0 then begin
+      lblInter.Caption := Format('提示:新增粮种 [%s-%s] 重名,提交失败!',[GrainType_rec.Name,glInput]);
+      exit;
+    end;
+    //新增粮种
+    AddGrainRecord(glInput, GrainType_rec);
+    //加载粮种列表
+    queryGrainlistSql(t_Grain, lbType2);
+    //界面信息提示
+    lblInter.Caption := Format('提示:新增粮种 [%s-%s] 成功!',[GrainType_rec.Name,glInput]);
+  end;
+
+  //清理现场
+  glInput := '';
+  frmInput.InitGrainRec();
+end;
+
+//修改粮种
+procedure TfrmMain.btnModfyClick(Sender: TObject);
+var
+  new,nam,nam1 : string;
+begin
+  {//确定选中的粮种名称
+  glCurrIndex := lbType2.ItemIndex;
+  if glCurrIndex<0 then exit;
+  nam := lbType2.Items[glCurrIndex];
+  new  := nam;
+  //启动手写输入框
+  frmTablet := TfrmTablet.Create(Application);  //创建动态窗体
+  frmTablet.strParam := nam;                    //传入修改值
+  frmTablet.ShowModal;                          //模态窗口显示Tablet
+  new := glInkOutput;
+  //判断是否重名,是否未改名
+  if new=nam then exit;
+  if Trim(new)='' then exit;
+  if queryGrainNumSql(t_Grain, new)>0 then begin
+    MessageBox(handle,'错误:您提交的粮种重名,请检查后重新提交!','错误对话框',MB_OK+MB_ICONERROR);
+    exit;
+  end;
+  //更新原始字符串
+  updateNameSql(t_Grain, new, nam);
+  Grain.Name := new;
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType2);
+  //更新标签
+  sLabel70.Caption := Format('粮食种类 - [%s]',[Grain.Name]); }
+  
+  {// 显示输入对话框,提示用户输入新字符串
+  if InputQuery('修改对话框', '请输入新的粮种名称:.', new) then
+  begin
+    //判断是否重名,是否未改名
+    if new=nam then exit;
+    if Trim(new)='' then exit;
+    if queryGrainNumSql(t_Grain, new)>0 then begin
+      MessageBox(handle,'错误:您提交的粮种重名,请检查后重新提交!','错误对话框',MB_OK+MB_ICONERROR);
+      exit;
+    end;
+    //更新原始字符串
+    updateNameSql(t_Grain, new, nam);
+    Grain.Name := new;
+    //加载粮种列表
+    queryGrainlistSql(t_Grain, lbType2);
+    //更新标签
+    sLabel70.Caption := Format('粮食种类 - [%s]',[Grain.Name]);
+  end;}
+  
+  //确定选中的粮种名称
+  glCurrIndex := lbType2.ItemIndex;
+  if glCurrIndex<0 then exit;
+  if Grain.flag then exit;
+
+  //打开触控板
+  ShellExecute(0, nil, 'OpenTabTip', nil, nil, SW_SHOWNORMAL);
+
+  nam := lbType2.Items[glCurrIndex];
+  new := nam;
+
+  //如果nam是:玉米-东北-->拆分为东北,传入真实nam
+  if  Pos('-', nam)>0 then
+    nam1 := SplitStr(nam, '-', 1);
+
+  //创建输入对话框
+  ShowInput(nam1, 1);
+  if GrainType_rec.Name='' then exit;
+  new := Format('%s-%s',[GrainType_rec.Name, glInput]);
+  
+  //判断是否重名,是否未改名
+  if new=nam then exit;
+  if Trim(new)='' then exit;
+  if queryGrainNumSql(t_Grain, glInput, GrainType_rec.Code)>0 then begin
+    lblInter.Caption := Format('提示:修改粮种 [%s-%s] 重名,提交失败!',[GrainType_rec.Name,glInput]);
+    exit;
+  end;
+  //更新粮种名称
+  updateNameSql(t_Grain, glInput, nam1, GrainType_rec.Code, Grain.Code);
+  Grain.Name := glInput;
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType2);
+  //更新标签,记录日志
+  sLabel70.Caption := Format('粮食种类 - [%s]',[Grain.Name]);
+  lblInter.Caption := Format('提示:修改粮种 [%s-%s] 成功!',[GrainType_rec.Name,Grain.Name]);
+  log4info(Format('提示:数据库 [%s] 粮食名称 [%s] 更新成功.',[t_Grain,Grain.Name]));
+  //清理全局变量
+  glInput := '';
+  frmInput.InitGrainRec();
+end;
+
+//删除粮种
+procedure TfrmMain.btnDelClick(Sender: TObject);
+var
+  nam : string;
+begin
+  //确定选中的粮种名称
+  glCurrIndex := lbType2.ItemIndex;
+  if glCurrIndex<0 then exit;
+  if Grain.flag then begin
+    MessageBox(handle,'错误:禁止删除大类粮种名称!','错误对话框',MB_OK+MB_ICONERROR);
+    exit;
+  end;
+
+  //删除粮种
+  nam := lbType2.Items[glCurrIndex];
+  deleteGrainSql(t_Grain, nam);
+  //加载粮种列表
+  queryGrainlistSql(t_Grain, lbType2);
+  //更新界面信息
+  sLabel70.Caption := '粮食种类';
+  lblInter.Caption := Format('提示:成功删除 [%s] 粮种信息!',[nam]);
+  log4info(lblInter.Caption);
+end;
+
+//------- 重量校准 -------------------------------------------------------------
+//手动测试一组数据
+procedure TfrmMain.btnWeightCoef1Click(Sender: TObject);
+var
+  index : Integer;
+  nWeight : Word;
+  nWeight1: SmallInt;
+begin
+  //获取当前Index
+  index := TsBitBtn(Sender).Tag;
+  //调用指令读取重量,强转为int
+  ReadWeight(hWrDev, @nWeight);
+  nWeight1 := SmallInt(nWeight);
+  //输出重量到界面
+  case TsBitBtn(Sender).Tag of
+    1: edtWTest1.Text := FloatToStr(nWeight1-StrToFloatDef(edtWTare.Text,0)); //去皮
+    2: edtWTest2.Text := FloatToStr(nWeight1-StrToFloatDef(edtWTare.Text,0));
+    3: edtWTest3.Text := FloatToStr(nWeight1-StrToFloatDef(edtWTare.Text,0));
+  end;
+  //显示结果
+  lblWeightCoef.Caption := Format('当前进行第 %d 组称重校准!', [index]);
+end;
+
+//校准后测试一次重量
+procedure TfrmMain.sBitBtn14Click(Sender: TObject);
+var
+  nWeight : Word;
+  nWeight1: SmallInt;
+  y : double;
+begin
+  //调用指令读取重量,强转为int
+  ReadWeight(hWrDev, @nWeight);
+  nWeight1 := SmallInt(nWeight);
+  //按公式计算y值
+  y := Wg.k * (nWeight1 - Wg.tare) + Wg.b;
+  edtWTest.Text := FloatToStr(y);
+  //显示结果
+  //提示保存成功!
+  if Wg.b>0 then
+    lblWeightCoef.Caption := Format('公式 Y = %.4fX + %.4f,校准后测试 %.4fg !', [Wg.k,Wg.b,y])
+  else
+    lblWeightCoef.Caption := Format('公式 Y = %.4fX - %.4f,校准后测试 %.4fg !', [Wg.k,Abs(Wg.b),y]);
+end;
+
+//设置手动去皮参数
+procedure TfrmMain.btnTareSetClick(Sender: TObject);
+begin
+  //将去皮重量存在全局重量参数中
+  Wg.tare := StrToFloatDef(edtWTare.Text,0);
+  Wg.range:= StrToFloatDef(edtRange.Text,0);
+  lblWeightCoef.Caption := Format('设置校准参数--去皮 %.4fg,误差范围 ±%.2f', [Wg.tare,Wg.range]);
+end;
+
+//计算重量校准系数
+procedure TfrmMain.sBitBtn11Click(Sender: TObject);
+var
+  std1,std2,std3 : double;
+  test1,test2,test3 : double;
+  y3, nK, nB : double;
+  range : double;  //误差范围
+begin
+  //设置误差范围
+  range := StrToFloatDef(edtRange.Text,0);
+  //保存实际重量
+  std1 := StrToFloatDef(edtWeight1.Text,0);
+  std2 := StrToFloatDef(edtWeight2.Text,0);
+  std3 := StrToFloatDef(edtWeight3.Text,0);
+  test1 := StrToFloatDef(edtWTest1.Text,0);
+  test2 := StrToFloatDef(edtWTest2.Text,0);
+  test3 := StrToFloatDef(edtWTest3.Text,0);
+  //计算校准系数k、b,校验误差范围
+  //公式 y=kx+b
+  nK := (std2 - std1)/(test2 - test1);
+  nB := std1 - nK * test1;
+  y3 := nK * test3 + nB;
+  //将k、b写入临时变量,验证偏差
+  glWg_k := nK;
+  glWg_b := nB;
+  if ((y3>=std3-range) and (y3<=std3+range)) then begin
+    if glWg_b>0 then
+      lblWeightCoef.Caption := Format('Y = %.4fX + %.4f,误差±%.2f,验证通过!', [glWg_k,glWg_b,range])
+    else
+      lblWeightCoef.Caption := Format('Y = %.4fX - %.4f,误差±%.2f,验证通过!', [glWg_k,Abs(glWg_b),range]);
+  end
+  else begin
+    if glWg_b>0 then
+      lblWeightCoef.Caption := Format('Y = %.4fX + %.4f 验证失败,未更新系数!', [glWg_k, glWg_b])
+    else
+      lblWeightCoef.Caption := Format('Y = %.4fX - %.4f 验证失败,未更新系数!', [glWg_k, Abs(glWg_b)]);
+  end;
+end;
+
+//保存重量系数
+procedure TfrmMain.sBitBtn12Click(Sender: TObject);
+begin
+  //更新重量校准参数
+  Wg.k := glWg_k;
+  Wg.b := glWg_b;
+  Wg.tare := StrToFloatDef(edtWTare.Text,0);
+  Wg.range:= StrToFloatDef(edtRange.Text,0);
+  Wg.test1 := StrToFloatDef(edtWTest1.Text,0);
+  Wg.test2 := StrToFloatDef(edtWTest2.Text,0);
+  Wg.test3 := StrToFloatDef(edtWTest3.Text,0);
+  Wg.std1 := StrToFloatDef(edtWeight1.Text,0);
+  Wg.std2 := StrToFloatDef(edtWeight2.Text,0);
+  Wg.std3 := StrToFloatDef(edtWeight3.Text,0);
+  //保存重量数据至数据库
+  SaveWgParam();
+  //提示保存成功!
+  if Wg.b>0 then
+    lblWeightCoef.Caption := Format('校准公式 Y = %.4fX + %.4f,误差±%.4f !', [Wg.k,Wg.b,Wg.range])
+  else
+    lblWeightCoef.Caption := Format('校准公式 Y = %.4fX - %.4f,误差±%.4f !', [Wg.k,Abs(Wg.b),Wg.range]);
+end;
+
+//------ 手动设置参数 ---------------------------------------------------------
+//手动写参数到水分仪
+procedure TfrmMain.btnSettingClick(Sender: TObject);
+var
+  ret : Integer;
+begin
+  //不用初始化连接设备,直接写参数
+  ret := WriteParams(hWrDev,
+                     StrToInt(edtStartFreq.Text),
+                     StrToInt(edtStopFreq.Text),
+                     StrToInt(edtStep.Text),
+                     StrToInt(edtDecay.Text),
+                     lbASK.ItemIndex);
+  if ret<0 then
+    MessageBox(handle,'提示:向水分仪下发参数失败,请检查后重新下发!','对话框',MB_OK+MB_ICONERROR)
+  else begin
+    //保存参数到数据库
+    SysConfig.StartFreq := StrToFloatDef(edtStartFreq.Text, 10500);
+    SysConfig.StopFreq := StrToFloatDef(edtStopFreq.Text, 12000);
+    SysConfig.Step := StrToIntDef(edtStep.Text, 50);
+    SysConfig.Freq := StrToFloatDef(edtFreq.Text, 0);
+    SysConfig.Decay := StrToFloatDef(edtDecay.Text, 1);
+    SysConfig.ASK   := lbASK.ItemIndex;
+    SysConfig.Volume := StrToFloatDef(edtVolume.Text, 0);
+    SysConfig.Tare := StrToFloatDef(edtTare.Text, 1000);
+    //调用数据库存储函数
+    SaveParam();
+    //弹框提示
+    MessageBox(handle, '提示:水分仪系统参数保存成功!', '保存对话框',MB_OK+MB_ICONINFORMATION);
+  end;
+end;
+
+//------- 系统信息设置 ---------------------------------------------------------
+//手动测试-调用虚拟键盘
+procedure TfrmMain.sBitBtn28Click(Sender: TObject);
+begin
+  //调用osk键盘
+  //OpenOnScreenKeyboard();
+  //打开触控板
+  ShellExecute(0, nil, 'OpenTabTip', nil, nil, SW_SHOWNORMAL);
+  //创建输入对话框
+  ShowInput(edtSampleName.Text);
+  edtSampleName.Text := glInput;
+  glInput := '';
+end;
+
+//系统信息-调用虚拟键盘
+procedure TfrmMain.btnOSKClick(Sender: TObject);
+begin
+  //打开触控板
+  ShellExecute(0, nil, 'OpenTabTip', nil, nil, SW_SHOWNORMAL);
+  //创建输入对话框
+  ShowInput(edtPrefix.Text);
+  edtPrefix.Text := glInput;
+  glInput := '';
+end;
+
+//选择数据保存的文件夹
+procedure TfrmMain.btnDirClick(Sender: TObject);
+var
+  dir: string;
+begin
+  if SelectDirectory('请选择存储文件夹','',dir) then begin
+    if RightStr(dir,1)='\' then
+      edtDir.Text := dir
+    else
+      edtDir.Text := dir + '\';
+  end;
+end;
+
+//------- 系统信息 -------------------------------------------------------------
+//保存系统信息
+procedure TfrmMain.btnSaveInfoClick(Sender: TObject);
+var
+  c : Char;
+  ss : string;
+begin
+  //把系统信息更新至全局数据结构
+  PlcConn.ip := edtIP.Text;
+  PlcConn.port := StrToIntDef(edtPort.Text,1502);
+  PlcConn.heart_ip := edtHeartIP.Text;
+  PlcConn.heart_port := StrToIntDef(edtHeartPort.Text,8868);
+  WrConn.SerialPort := cbSerialPort.Text;
+  WrConn.baud := StrToIntDef(edtBaud.Text,115200);
+  //单独处理char类型
+  CopyMemory(@c, PChar(edtParity.Text), 1);
+  WrConn.parity := c;
+  WrConn.data_bit := StrToIntDef(edtData_bit.Text,8);
+  WrConn.stop_bit := StrToIntDef(edtStop_bit.Text,1);
+  glTime1 := StrToIntDef(edtTime1.Text,2);
+  glTime2 := StrToIntDef(edtTime2.Text,20);
+
+  //更新启动选项
+  ss := '"'+ glAppPath + Application.ExeName +'"';
+  if cbAutoRun.Checked then glAutoRun := true
+  else glAutoRun := false;
+  AutoRun(glAutoRun, 'GmmSoft');
+
+  //增加调试开关
+  glIsDebug := cbDebug.Checked;
+  //更新存储参数
+  smp.flag := cbAutoSave.Checked;
+  smp.prefix := edtPrefix.Text;
+  smp.dir := edtDir.Text;
+  cbTestAutoSave.Checked := cbAutoSave.Checked; //同步手动检测界面
+
+  //增加登录口令
+  SysConfig.password := edtPassword.Text;
+  SysConfig.delay := StrToIntDef(edtDelay.Text,0);
+  
+  //调用数据库存储函数
+  SaveParam();
+  //弹框提示
+  MessageBox(handle, '提示:扦捡系统、水分仪、检测参数保存成功!', '保存对话框',MB_OK+MB_ICONINFORMATION);
+end;
+
+//复位
+procedure TfrmMain.btnResetClick(Sender: TObject);
+var
+  ret : Integer;
+begin
+  ret := SendCommands(hWrDev, WR_RESET, 0, glTime1);
+  if ret=0 then begin
+    ResponseState(hPlcDev, PLC_DEVICE_WR_FAULT);
+    //弹框提示
+    MessageBox(handle, '提示:执行水分仪复位操作成功!', '对话框',MB_OK+MB_ICONINFORMATION);
+  end;
+end;
+
+//------- 仪器维护 ----------------------------------------
+//仪器复位功能子函数
+procedure TfrmMain.SetResetUI(flag:boolean);
+begin
+  sBitBtn16.Enabled := flag;
+  sBitBtn17.Enabled := flag;
+  sBitBtn18.Enabled := flag;
+  sBitBtn19.Enabled := flag;
+  sBitBtn20.Enabled := flag;
+  sBitBtn21.Enabled := flag;
+  sBitBtn22.Enabled := flag;
+  sBitBtn23.Enabled := flag;
+  sBitBtn24.Enabled := flag;
+  sBitBtn25.Enabled := flag;
+  sBitBtn26.Enabled := flag;
+end;
+
+//进入仪器维护界面
+procedure TfrmMain.sBitBtn15Click(Sender: TObject);
+begin
+  pc.ActivePage := tsMaintain;
+end;
+
+//仪器复位
+procedure TfrmMain.sBitBtn18Click(Sender: TObject);
+begin
+  //启动仪器复位线程
+  if m_ResetThread=0 then begin
+    //设置按钮不可用
+    SetResetUI(false);
+    //启动线程
+    resetThread := TResetThread.Create();
+    m_resetThread := resetThread.Handle;
+  end
+  else
+    lblMaintain.Caption := '仪器复位尚未结束,请稍后再试!';
+end;
+
+//显示固件版本
+procedure TfrmMain.sBitBtn17Click(Sender: TObject);
+var
+  ver : array[0..1] of Word; //暂存版本号
+  ret : Integer;
+  faultCode : Word;          //水分仪故障码
+begin
+  //检查水分仪故障码
+  ReadFaultCode(hWrDev, @faultCode);
+  RefashFaultCode(faultCode);
+
+  //初始化版本数组
+  ver[0] := 0;
+  ver[1] := 0;
+
+  ret := ReadVersion(hWrDev, @ver);
+  if ret>0 then
+    lblMaintain.Caption := Format('提示:水分仪硬件版本 [%d], 软件版本 [%d].', [ver[0],ver[1]])
+  else
+    lblMaintain.Caption := '提示:读取水分仪固件版本号失败!';
+end;
+
+//------- 按钮事件 -------------------------------------------------------------
+//仪器维护界面按钮事件
+procedure TfrmMain.sBitBtn19Click(Sender: TObject);
+var
+  ret : Integer;
+  faultCode : Word;          //水分仪故障码
+begin
+  //执行水分仪维护指令
+  ret := 0;
+  case TsBitBtn(Sender).Tag of
+    1: ret := SendCommands(hWrDev, WR_VALV01,0,15,0); //上阀门开
+    2: ret := SendCommands(hWrDev, WR_VALV02,0,15,0); //上阀门关
+    3: ret := SendCommands(hWrDev, WR_VALV03,0,15,0); //下阀门开
+    4: ret := SendCommands(hWrDev, WR_VALV04,0,15,0); //下阀门关
+    5: ret := SendCommands(hWrDev, WR_VALV05,0,15,0); //双阀门开
+    6: ret := SendCommands(hWrDev, WR_VALV06,0,15,0); //双阀门关
+    7: ret := SendCommands(hWrDev, WR_VIBRATE_01,0,15,0); //振动开
+    8: ret := SendCommands(hWrDev, WR_VIBRATE_02,0,15,0); //振动关
+  end;
+  //显示执行结果
+  if ret=0 then
+    lblMaintain.Caption := '提示:执行水分仪 ['+TsBitBtn(Sender).Caption+'] 操作成功!'
+  else
+    lblMaintain.Caption := '提示:执行水分仪 ['+TsBitBtn(Sender).Caption+'] 操作失败!';
+
+  //检查水分仪故障码
+  ReadFaultCode(hWrDev, @faultCode);
+  RefashFaultCode(faultCode);
+end;
+
+procedure TfrmMain.sImage4Click(Sender: TObject);
+begin
+  // 使窗体在任务栏上可见
+  Application.Minimize;
+end;
+
+end.

--
Gitblit v1.9.3