unit Comm;
interface uses Messages, WinTypes, WinProcs, Classes, Forms;
type
TPort = (tptNone, tptOne, tptTwo, tptThree, tptFour, tptFive, tptSix, tptSeven, tptEight); TBaudRate = (tbr110, tbr300, tbr600, tbr1200, tbr2400, tbr4800, tbr9600, tbr14400, tbr19200, tbr38400, tbr56000, tbr128000, tbr256000); TParity = (tpNone, tpOdd, tpEven, tpMark, tpSpace); TDataBits = (tdbFour, tdbFive, tdbSix, tdbSeven, tdbEight); TStopBits = (tsbOne, tsbOnePointFive, tsbTwo); TCommEvent = (tceBreak, tceCts, tceCtss, tceDsr, tceErr, tcePErr, tceRing, tceRlsd, tceRlsds, tceRxChar, tceRxFlag, tceTxEmpty); TCommEvents = set of TCommEvent;
const
PortDefault = tptNone; BaudRateDefault = tbr9600; ParityDefault = tpNone; DataBitsDefault = tdbEight; StopBitsDefault = tsbOne; ReadBufferSizeDefault = 2048; WriteBufferSizeDefault = 2048; RxFullDefault = 1024; TxLowDefault = 1024; EventsDefault = [];
type
TNotifyEventEvent = procedure(Sender: TObject; CommEvent: TCommEvents) of object; TNotifyReceiveEvent = procedure(Sender: TObject; Count: Word) of object; TNotifyTransmitEvent = procedure(Sender: TObject; Count: Word) of object;
TComm = class(TComponent) private FPort: TPort; FBaudRate: TBaudRate; FParity: TParity; FDataBits: TDataBits; FStopBits: TStopBits; FReadBufferSize: Word; FWriteBufferSize: Word; FRxFull: Word; FTxLow: Word; FEvents: TCommEvents; FOnEvent: TNotifyEventEvent; FOnReceive: TNotifyReceiveEvent; FOnTransmit: TNotifyTransmitEvent; FWindowHandle: hWnd; hComm: Integer; HasBeenLoaded: Boolean; Error: Boolean; procedure SetPort(Value: TPort); procedure SetBaudRate(Value: TBaudRate); procedure SetParity(Value: TParity); procedure SetDataBits(Value: TDataBits); procedure SetStopBits(Value: TStopBits); procedure SetReadBufferSize(Value: Word); procedure SetWriteBufferSize(Value: Word); procedure SetRxFull(Value: Word); procedure SetTxLow(Value: Word); procedure SetEvents(Value: TCommEvents); procedure WndProc(var Msg: TMessage); procedure DoEvent; procedure DoReceive; procedure DoTransmit; protected procedure Loaded; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Write(Data: PChar; Len: Word); procedure Read(Data: PChar; Len: Word); function IsError: Boolean; published property Port: TPort read FPort write SetPort default PortDefault; property BaudRate: TBaudRate read FBaudRate write SetBaudRate default BaudRateDefault; property Parity: TParity read FParity write SetParity default ParityDefault; property DataBits: TDataBits read FDataBits write SetDataBits default DataBitsDefault; property StopBits: TStopBits read FStopBits write SetStopBits default StopBitsDefault; property WriteBufferSize: Word read FWriteBufferSize write SetWriteBufferSize default WriteBufferSizeDefault; property ReadBufferSize: Word read FReadBufferSize write SetReadBufferSize default ReadBufferSizeDefault; property RxFullCount: Word read FRxFull write SetRxFull default RxFullDefault; property TxLowCount: Word read FTxLow write SetTxLow default TxLowDefault; property Events: TCommEvents read FEvents write SetEvents default EventsDefault; property OnEvent: TNotifyEventEvent read FOnEvent write FOnEvent; property OnReceive: TNotifyReceiveEvent read FOnReceive write FOnReceive; property OnTransmit: TNotifyTransmitEvent read FOnTransmit write FOnTransmit; end;
procedure Register;
implementation
procedure TComm.SetPort(Value: TPort); const
CommStr: PChar = 'COM1:'; begin
FPort := Value; if (csDesigning in ComponentState) or (Value = tptNone) or (not HasBeenLoaded) then exit; if hComm >= 0 then CloseComm(hComm); CommStr[3] := chr(48 + ord(Value)); hComm := OpenComm(CommStr, ReadBufferSize, WriteBufferSize); if hComm < 0 then begin Error := True; exit; end; SetBaudRate(FBaudRate); SetParity(FParity); SetDataBits(FDataBits); SetStopBits(FStopBits); SetEvents(FEvents); EnableCommNotification(hComm, FWindowHandle, FRxFull, FTxLow); end;
procedure TComm.SetBaudRate(Value: TBaudRate); var
DCB: TDCB; begin
FBaudRate := Value; if hComm >= 0 then begin GetCommState(hComm, DCB); case Value of tbr110: DCB.BaudRate := CBR_110; tbr300: DCB.BaudRate := CBR_300; tbr600: DCB.BaudRate := CBR_600; tbr1200: DCB.BaudRate := CBR_1200; tbr2400: DCB.BaudRate := CBR_2400; tbr4800: DCB.BaudRate := CBR_4800; tbr9600: DCB.BaudRate := CBR_9600; tbr14400: DCB.BaudRate := CBR_14400; tbr19200: DCB.BaudRate := CBR_19200; tbr38400: DCB.BaudRate := CBR_38400; tbr56000: DCB.BaudRate := CBR_56000; tbr128000: DCB.BaudRate := CBR_128000; tbr256000: DCB.BaudRate := CBR_256000; end; SetCommState(DCB); end; end;
procedure TComm.SetParity(Value: TParity); var
DCB: TDCB; begin
FParity := Value; if hComm < 0 then exit; GetCommState(hComm, DCB); case Value of tpNone: DCB.Parity := 0; tpOdd: DCB.Parity := 1; tpEven: DCB.Parity := 2; tpMark: DCB.Parity := 3; tpSpace: DCB.Parity := 4; end; SetCommState(DCB); end;
procedure TComm.SetDataBits(Value: TDataBits); var
DCB: TDCB; begin
FDataBits := Value; if hComm < 0 then exit; GetCommState(hComm, DCB); case Value of tdbFour: DCB.ByteSize := 4; tdbFive: DCB.ByteSize := 5; tdbSix: DCB.ByteSize := 6; tdbSeven: DCB.ByteSize := 7; tdbEight: DCB.ByteSize := 8; end; SetCommState(DCB); end;
procedure TComm.SetStopBits(Value: TStopBits); var
DCB: TDCB; begin
FStopBits := Value; if hComm < 0 then exit; GetCommState(hComm, DCB); case Value of tsbOne: DCB.StopBits := 0; tsbOnePointFive: DCB.StopBits := 1; tsbTwo: DCB.StopBits := 2; end; SetCommState(DCB); end;
procedure TComm.SetReadBufferSize(Value: Word); begin
FReadBufferSize := Value; SetPort(FPort); end;
procedure TComm.SetWriteBufferSize(Value: Word); begin
FWriteBufferSize := Value; SetPort(FPort); end;
procedure TComm.SetRxFull(Value: Word); begin
FRxFull := Value; if hComm < 0 then exit; EnableCommNotification(hComm, FWindowHandle, FRxFull, FTxLow); end;
procedure TComm.SetTxLow(Value: Word); begin
FTxLow := Value; if hComm < 0 then exit; EnableCommNotification(hComm, FWindowHandle, FRxFull, FTxLow); end;
procedure TComm.SetEvents(Value: TCommEvents); var
EventMask: Word; begin
FEvents := Value; if hComm < 0 then exit; EventMask := 0; if tceBreak in FEvents then inc(EventMask, EV_BREAK); if tceCts in FEvents then inc(EventMask, EV_CTS); if tceCtss in FEvents then inc(EventMask, EV_CTSS); if tceDsr in FEvents then inc(EventMask, EV_DSR); if tceErr in FEvents then inc(EventMask, EV_ERR); if tcePErr in FEvents then inc(EventMask, EV_PERR); if tceRing in FEvents then inc(EventMask, EV_RING); if tceRlsd in FEvents then inc(EventMask, EV_RLSD); if tceRlsds in FEvents then inc(EventMask, EV_RLSDS); if tceRxChar in FEvents then inc(EventMask, EV_RXCHAR); if tceRxFlag in FEvents then inc(EventMask, EV_RXFLAG); if tceTxEmpty in FEvents then inc(EventMask, EV_TXEMPTY); SetCommEventMask(hComm, EventMask); end;
procedure TComm.WndProc(var Msg: TMessage); begin
with Msg do begin if Msg = WM_COMMNOTIFY then begin case lParamLo of CN_EVENT: DoEvent; CN_RECEIVE: DoReceive; CN_TRANSMIT: DoTransmit; end; end else Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); end; end;
procedure TComm.DoEvent; var
CommEvent: TCommEvents; EventMask: Word; begin
if (hComm < 0) or not Assigned(FOnEvent) then exit; EventMask := GetCommEventMask(hComm, Integer($FFFF)); CommEvent := []; if (tceBreak in Events) and (EventMask and EV_BREAK <> 0) then CommEvent := CommEvent + [tceBreak]; if (tceCts in Events) and (EventMask and EV_CTS <> 0) then CommEvent := CommEvent + [tceCts]; if (tceCtss in Events) and (EventMask and EV_CTSS <> 0) then CommEvent := CommEvent + [tceCtss]; if (tceDsr in Events) and (EventMask and EV_DSR <> 0) then CommEvent := CommEvent + [tceDsr]; if (tceErr in Events) and (EventMask and EV_ERR <> 0) then CommEvent := CommEvent + [tceErr]; if (tcePErr in Events) and (EventMask and EV_PERR <> 0) then CommEvent := CommEvent + [tcePErr]; if (tceRing in Events) and (EventMask and EV_RING <> 0) then CommEvent := CommEvent + [tceRing]; if (tceRlsd in Events) and (EventMask and EV_RLSD <> 0) then CommEvent := CommEvent + [tceRlsd]; if (tceRlsds in Events) and (EventMask and EV_Rlsds <> 0) then CommEvent := CommEvent + [tceRlsds]; if (tceRxChar in Events) and (EventMask and EV_RXCHAR <> 0) then CommEvent := CommEvent + [tceRxChar]; if (tceRxFlag in Events) and (EventMask and EV_RXFLAG <> 0) then CommEvent := CommEvent + [tceRxFlag]; if (tceTxEmpty in Events) and (EventMask and EV_TXEMPTY <> 0) then CommEvent := CommEvent + [tceTxEmpty]; FOnEvent(Self, CommEvent); end;
procedure TComm.DoReceive; var
Stat: TComStat; begin
if (hComm < 0) or not Assigned(FOnReceive) then exit; GetCommError(hComm, Stat); FOnReceive(Self, Stat.cbInQue); GetCommError(hComm, Stat); end;
procedure TComm.DoTransmit; var Stat: TComStat; begin if (hComm < 0) or not Assigned(FOnTransmit) then exit; GetCommError(hComm, Stat); FOnTransmit(Self, Stat.cbOutQue); end;
procedure TComm.Loaded; begin inherited Loaded; HasBeenLoaded := True; SetPort(FPort); end;
constructor TComm.Create(AOwner: TComponent); begin inherited Create(AOwner); FWindowHandle := AllocateHWnd(WndProc); HasBeenLoaded := False; Error := False; FPort := PortDefault; FBaudRate := BaudRateDefault; FParity := ParityDefault; FDataBits := DataBitsDefault; FStopBits := StopBitsDefault; FWriteBufferSize := WriteBufferSizeDefault; FReadBufferSize := ReadBufferSizeDefault; FRxFull := RxFullDefault; FTxLow := TxLowDefault; FEvents := EventsDefault; hComm := -1; end;
destructor TComm.Destroy; begin DeallocatehWnd(FWindowHandle); if hComm >= 0 then CloseComm(hComm); inherited Destroy; end;
procedure TComm.Write(Data: PChar; Len: Word); begin if hComm < 0 then exit; if WriteComm(hComm, Data, Len) < 0 then Error := True; GetCommEventMask(hComm, Integer($FFFF)); end;
procedure TComm.Read(Data: PChar; Len: Word); begin if hComm < 0 then exit; if ReadComm(hComm, Data, Len) < 0 then Error := True; GetCommEventMask(hComm, Integer($FFFF)); end;
function TComm.IsError: Boolean; begin IsError := Error; Error := False; end;
procedure Register; begin RegisterComponents('Additional', [TComm]); end;
end.
|