unit uComm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, SPComm, Buttons,uFunMesClient;

type
  TfrmComm = class(TForm)
    ComboBox1: TComboBox;
    Label3: TLabel;
    Label4: TLabel;
    ComboBox2: TComboBox;
    Comm1: TComm;
    ImageOn: TImage;
    ImageOff: TImage;
    btnSwitch: TButton;
    ComboBox3: TComboBox;
    Label5: TLabel;
    Label6: TLabel;
    ComboBox4: TComboBox;
    Label7: TLabel;
    ComboBox5: TComboBox;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
    procedure btnSwitchClick(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ComboBox2Change(Sender: TObject);
    procedure ComboBox3Change(Sender: TObject);
    procedure ComboBox4Change(Sender: TObject);
    procedure ComboBox5Change(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    procedure ShowStatus;
    procedure IniSetForm;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmComm: TfrmComm;
Const
  ComStr = 'ComName=%s,BaudRate=%S,Parity=%S,ByteSize=%S,StopBits=%S' ;
implementation

{$R *.dfm}
function StrToHexStr(const S:string):string;
//字符串转换成16进制字符串
var
  I:Integer;
begin
  for I:=1 to Length(S) do
  begin
    if I=1 then
      Result:=IntToHex(Ord(S[1]),2)
    else Result:=Result+' '+IntToHex(Ord(S[I]),2);
  end;
end;

procedure TfrmComm.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  BufferLength: Word);
var
  str :string;
begin
 { //Memo自动清空
  if (Memo1.Lines.Count > 50) then Memo1.Clear;

  SetLength(Str,BufferLength);
  move(buffer^,pchar(@Str[1])^,bufferlength);

    if cbRecHex.Checked then
      Memo1.Text:=Memo1.Text+StrToHexStr(Str)+' '
    else
      Memo1.Text := Memo1.Text + Str;
  Memo1.SelStart := Length(Memo1.Text);
  Memo1.SelLength:= 0;
  Memo1.Perform(EM_SCROLLCARET,0,0);  
  Application.HandleMessage;  }

end;



procedure TfrmComm.btnSwitchClick(Sender: TObject);
var
  BaudRate :integer;
begin
  if btnSwitch.Caption = '打开串口' then
  begin
    if not TryStrToInt(ComboBox2.Text,BaudRate) then
    begin
      Application.MessageBox('波特率设定有误'+#13+  ' 请重新输入','警告',MB_ICONWARNING or MB_OK);
      ComboBox2.SetFocus;
      exit;
    end;   
    Comm1.StartComm;
    btnSwitch.Caption := '关闭串口';
    ImageOff.Visible  := false;
    ImageOn.Visible   :=true;
  end
  else //if Button1.Caption = '关闭串口' then
  begin
    Comm1.StopComm;
    btnSwitch.Caption := '打开串口';
    ComboBox1.Enabled := true;
    ComboBox2.Enabled := true;
    ImageOn.Visible   := false;
    ImageOff.Visible  :=true;
  end;
  ShowStatus;
end;

procedure EnumComPorts(Ports: TStrings);
var
  KeyHandle: HKEY;
  ErrCode, Index: Integer;
  ValueName, Data: string;
  ValueLen, DataLen, ValueType: DWORD;
  TmpPorts: TStringList;
begin
  ErrCode := RegOpenKeyEx(
    HKEY_LOCAL_MACHINE,
    'HARDWARE\DEVICEMAP\SERIALCOMM',
    0,
    KEY_READ,
    KeyHandle);

  if ErrCode <> ERROR_SUCCESS then
    Exit;  // raise EComPort.Create(CError_RegError, ErrCode);

  TmpPorts := TStringList.Create;
  try
    Index := 0;
    repeat
      ValueLen := 256;
      DataLen := 256;
      SetLength(ValueName, ValueLen);
      SetLength(Data, DataLen);
      ErrCode := RegEnumValue(
        KeyHandle,
        Index,
        PChar(ValueName),
        Cardinal(ValueLen),
        nil,
        @ValueType,
        PByte(PChar(Data)),
        @DataLen);

      if ErrCode = ERROR_SUCCESS then
      begin
        SetLength(Data, DataLen);
        TmpPorts.Add(Data);
        Inc(Index);
      end
      else
        if ErrCode <> ERROR_NO_MORE_ITEMS then
          exit; //raise EComPort.Create(CError_RegError, ErrCode);

    until (ErrCode <> ERROR_SUCCESS) ;

    TmpPorts.Sort;
    Ports.Assign(TmpPorts);
  finally
    RegCloseKey(KeyHandle);
    TmpPorts.Free;
  end;
end;

procedure TfrmComm.ComboBox1Change(Sender: TObject);
begin
  Comm1.CommName:=ComboBox1.Text;
end;

procedure TfrmComm.FormCreate(Sender: TObject);
begin

  EnumComPorts(ComboBox1.Items);    //得到串口列表
  ComboBox1.ItemIndex := 0;
  Comm1.CommName := ComboBox1.Text;
  ComboBox2.ItemIndex := 6;
  Comm1.BaudRate := StrToInt(ComboBox2.Text);
  ComboBox3.ItemIndex := 0;
  Comm1.Parity := None;
  ComboBox4.ItemIndex := 3;
  Comm1.ByteSize := _8;
  ComboBox5.ItemIndex := 0;
  Comm1.StopBits := _1;
  IniSetForm ;
end;

procedure TfrmComm.ComboBox2Change(Sender: TObject);
var
  BaudRate : Integer;
begin
  if ComboBox2.Text = 'Custom' then
  begin
    ComboBox2.Style := csDropDown;
    ComboBox2.SetFocus;
  end
  else 
  begin
    if  ComboBox2.ItemIndex >0 then
      ComboBox2.Style := csDropDownList;
    if TryStrToInt(ComboBox2.Text,BaudRate) then
           Comm1.BaudRate := BaudRate;
  end;
end;

procedure TfrmComm.ComboBox3Change(Sender: TObject);
begin
  Comm1.Parity := TParity(ComboBox3.ItemIndex);
end;

procedure TfrmComm.ComboBox4Change(Sender: TObject);
begin
  Comm1.ByteSize :=  TByteSize(ComboBox4.ItemIndex);
end;

procedure TfrmComm.ComboBox5Change(Sender: TObject);
begin
  Comm1.StopBits := TStopBits(ComboBox5.ItemIndex);
end;

procedure TfrmComm.ShowStatus;
begin
  if btnSwitch.Caption = '关闭串口' then
  begin
    Caption :=Format(' STATUS: %s Opened %s %s %s %s',[ComboBox1.Text,
      {ComboBox2.Text,}IntToStr(Comm1.BaudRate),ComboBox3.Text,ComboBox4.Text,ComboBox5.Text]);
  end
  else Caption :=' STATUS: COM Port Closed';
end;


procedure TfrmComm.BitBtn1Click(Sender: TObject);
var
  S: String;
begin    
  S := Format(ComStr,[ComboBox1.text,ComboBox2.Text,ComboBox3.Text,ComboBox4.Text,ComboBox5.Text]);
  SaveToIni(S);
end;

procedure TfrmComm.IniSetForm;
var
  tmpLst: TStringList;
begin
  tmpLst := TStringList.Create;
  tmpLst.Delimiter := ',';
  tmpLst.DelimitedText := ReadFromIni;
  ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(tmpLst.Values['ComName']);
  ComboBox2.ItemIndex := ComboBox2.Items.IndexOf(tmpLst.Values['BaudRate']);
  ComboBox3.ItemIndex := ComboBox3.Items.IndexOf(tmpLst.Values['Parity']);
  ComboBox4.ItemIndex := ComboBox4.Items.IndexOf(tmpLst.Values['ByteSize']);
  ComboBox5.ItemIndex := ComboBox5.Items.IndexOf(tmpLst.Values['StopBits'])
end;

end.
