📄 commint.pas
字号:
inherited Destroy;
end;
procedure TCustomComm.Lock;
begin
FCriticalSection.Enter;
end;
procedure TCustomComm.Unlock;
begin
FCriticalSection.Leave;
end;
function TCustomComm.Enabled: Boolean;
begin
Result := FHandle <> INVALID_HANDLE_VALUE;
end;
procedure TCustomComm.CheckOpen;
begin
if Enabled then RaiseCommError(sPortAlreadyOpen, -1);
end;
procedure TCustomComm.CreateHandle;
begin
FHandle := CreateFile(PCHAR(FDeviceName),
GENERIC_READ or GENERIC_WRITE, 0, nil,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if not Enabled then
RaiseCommError(sOpenError, GetLastError);
if GetFileType(FHandle) <> FILE_TYPE_CHAR then
begin
DestroyHandle;
RaiseCommError(sInvalidHandle, -1);
end;
end;
procedure TCustomComm.DestroyHandle;
begin
CloseHandle(FHandle);
FHandle := INVALID_HANDLE_VALUE;
end;
procedure TCustomComm.Open;
begin
CheckOpen;
CreateHandle;
if Enabled then
begin
FEventThread := TCommEventThread.Create(FHandle, FMonitorEvents);
FEventThread.OnSignal := HandleCommEvent;
UpdateCommTimeouts;
UpdateDataControlBlock;
if not SetupComm(FHandle, FReadBufSize, FWriteBufSize) then
RaiseCommError(sSetupCommErr, GetLastError);
end;
end;
procedure TCustomComm.Close;
begin
if Enabled then
begin
FEventThread.Terminate;
DestroyHandle;
end;
end;
function TCustomComm.Write(var Buf; Count: Integer): Integer;
var
Overlapped: TOverlapped;
ErrorCode: Integer;
begin
Lock;
try
FillChar(Overlapped, Sizeof(Overlapped), 0);
Overlapped.hEvent := FEvent.Handle;
if not WriteFile(FHandle, Buf, Count, dWord(Result),
@Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
begin
ErrorCode := GetLastError;
RaiseCommError(sWriteError, ErrorCode);
end;
if FEvent.WaitFor(FWriteTimeout) <> wrSignaled then
Result := -1
else
begin
GetOverlappedResult(Handle, Overlapped, dWord(Result), False);
FEvent.ResetEvent;
end;
finally
Unlock;
end;
end;
function TCustomComm.Read(var Buf; Count: Integer): Integer;
var
Overlapped: TOverlapped;
ErrorCode: Integer;
begin
Lock;
try
FillChar(Overlapped, Sizeof(Overlapped), 0);
Overlapped.hEvent := FEvent.Handle;
if not ReadFile(FHandle, Buf, Count, dWord(Result),
@Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
begin
ErrorCode := GetLastError;
RaiseCommError(sReadError, ErrorCode);
end;
if FEvent.WaitFor(FReadTimeout) <> wrSignaled then
Result := -1
else
begin
GetOverlappedResult(Handle, Overlapped, dWord(Result), False);
FEvent.ResetEvent;
end;
finally
Unlock;
end;
end;
function TCustomComm.InQueCount: Integer;
var
ComStat: TComStat;
Errors: dword;
begin
if Enabled then
begin
ClearCommError(FHandle, Errors, @ComStat);
Result := ComStat.cbInQue;
end else Result := -1;
end;
function TCustomComm.OutQueCount: Integer;
var
ComStat: TComStat;
Errors: dword;
begin
if Enabled then
begin
ClearCommError(FHandle, Errors, @ComStat);
Result := ComStat.cbOutQue;
end else Result := -1;
end;
procedure TCustomComm.PurgeIn;
begin
if Enabled then
PurgeComm(FHandle, PurgeRead);
end;
procedure TCustomComm.PurgeOut;
begin
if Enabled then
PurgeComm(FHandle, PurgeWrite);
end;
procedure TCustomComm.SetDeviceName(const Value: string);
begin
if FDeviceName <> Value then
begin
CheckOpen;
FDeviceName := Value;
end;
end;
procedure TCustomComm.SetMonitorEvents(Value: TCommEventTypes);
begin
if FMonitorEvents <> Value then
begin
CheckOpen;
FMonitorEvents := Value;
end;
end;
procedure TCustomComm.SetReadBufSize(Value: Integer);
begin
if FReadBufSize <> Value then
begin
CheckOpen;
FReadBufSize := Value;
end;
end;
procedure TCustomComm.SetWriteBufSize(Value: Integer);
begin
if FWriteBufSize <> Value then
begin
CheckOpen;
FWriteBufSize := Value;
end;
end;
procedure TCustomComm.SetBaudRate(Value: TBaudRate);
begin
if FBaudRate <> Value then
begin
FBaudRate := Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.SetParity(Value: TParity);
begin
if FParity <> Value then
begin
FParity := Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.SetStopbits(Value: TStopbits);
begin
if FStopBits <> Value then
begin
FStopbits := Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.SetDataBits(Value: TDatabits);
begin
if FDataBits <> Value then
begin
FDataBits:=Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.SetOptions(Value: TCommOptions);
begin
if FOptions <> Value then
begin
FOptions := Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.SetFlowControl(Value: TFlowControl);
begin
if FFlowControl <> Value then
begin
FFlowControl := Value;
UpdateDataControlBlock;
end;
end;
procedure TCustomComm.HandleCommEvent(Sender: TObject; Status: dword);
var
ComStat: TComStat;
Errors: dword;
begin
ClearCommError(FHandle, Errors, @ComStat);
if Status and EV_BREAK > 0 then
if assigned(FOnBreak) then FOnBreak(self);
if Status and EV_CTS > 0 then
if assigned(FOnCts) then FOnCts(self);
if Status and EV_DSR > 0 then
if assigned(FOnDsr) then FOnDsr(self);
if Status and EV_ERR > 0 then
if assigned(FOnError) then FOnError(self, Errors);
if Status and EV_RING > 0 then
if assigned(FOnRing) then FOnRing(self);
if Status and EV_RLSD > 0 then
if assigned(FOnRlsd) then FOnRlsd(self);
if Status and EV_RXCHAR > 0 then
if ComStat.cbInQue > 0 then
if assigned(FOnRxChar) then FOnRxChar(self, ComStat.cbInQue);
if Status and EV_RXFLAG > 0 then
if assigned(FOnRxFlag) then FOnRxFlag(self);
if Status and EV_TXEMPTY > 0 then
if assigned(FOnTxEmpty) then FOnTxEmpty(self);
end;
function TCustomComm.GetModemState(Index: Integer): boolean;
var
Flag, State: dword;
begin
case Index of
1: State := MS_CTS_ON;
2: State := MS_DSR_ON;
3: State := MS_RING_ON;
4: State := MS_RLSD_ON;
else
State := 0;
end;
Result := false;
if Enabled then
if GetCommModemStatus(FHandle, Flag) then
Result := (Flag and State > 0);
end;
function TCustomComm.GetComState(Index: Integer): Boolean;
var
Flag: TComStateFlag;
ComStat: TComStat;
Errors: dword;
begin
case Index of
1: Flag := fCtlHold;
2: Flag := fDsrHold;
3: Flag := fRlsHold;
4: Flag := fXoffHold;
5: Flag := fXOffSent;
else
Flag := fCtlHold;
end;
Result := false;
if Enabled then
begin
ClearCommError(FHandle, Errors, @ComStat);
Result := Flag in ComStat.Flags;
end;
end;
procedure TCustomComm.UpdateDataControlBlock;
var
OptIndex: TCommOption;
begin
if Enabled then
begin
GetCommState(FHandle, FDCB);
FDCB.BaudRate := CommBaudRates[FBaudRate];
FDCB.Parity := CommParity[FParity];
FDCB.Stopbits := CommStopbits[FStopbits];
FDCB.Bytesize := CommDatabits[FDatabits];
FDCB.XonChar := FEventChars.XonChar;
FDCB.XoffChar := FEventChars.XOffChar;
FDCB.ErrorChar := FEventChars.ErrorChar;
FDCB.EofChar := FEventChars.EofChar;
FDCB.EvtChar := FEventChars.EvtChar;
FDCB.XonLim := FReadBufSize div 4;
FDCB.XoffLim := FReadBufSize div 4;
InitHandshaking(FDCB);
for OptIndex := coParityCheck to coNullStrip do
if OptIndex in FOptions then FDCB.Flags := FDCB.Flags or CommOptions[OptIndex]
else FDCB.Flags := FDCB.Flags and not CommOptions[OptIndex];
if not SetCommState(FHandle, FDCB) then
RaiseCommError(sUpdateDCBErr, GetLastError);
end;
end;
procedure TCustomComm.EscapeComm(Flag: Integer);
var
Escaped: Boolean;
begin
if Enabled then
begin
Escaped := EscapeCommFunction(FHandle, Flag);
if not Escaped then
RaiseCommError(SEscFuncError, GetLastError);
end else RaiseCommError(SPortNotOpen, -1);
end;
procedure TCustomComm.SetDTRState(State: boolean);
const
DTR: array[boolean] of Integer = (CLRDTR, SETDTR);
begin
EscapeComm(DTR[State]);
end;
procedure TCustomComm.SetRTSState(State: boolean);
const
RTS: array[boolean] of Integer = (CLRRTS, SETRTS);
begin
EscapeComm(RTS[State]);
end;
procedure TCustomComm.SetBREAKState(State: Boolean);
const
BREAK: array[boolean] of Integer = (CLRBREAK, SETBREAK);
begin
EscapeComm(BREAK[State]);
if Enabled then
PurgeComm(FHandle, PurgeReadWrite);
end;
procedure TCustomComm.SetXONState(State: Boolean);
const
XON: array[boolean] of Integer = (SETXOFF, SETXON);
begin
EscapeComm(XON[State]);
end;
procedure TCustomComm.UpdateCommTimeouts;
var
CommTimeouts: TCommTimeouts;
begin
FillChar(CommTimeOuts, Sizeof(CommTimeOuts), 0);
CommTimeOuts.ReadIntervalTimeout := MAXDWORD;
if not SetCommTimeOuts(FHandle, CommTimeOuts) then
RaiseCommError(sCommTimeoutsErr, GetLastError);
end;
procedure TCustomComm.InitHandshaking(var DCB: TDCB);
begin
case FFlowControl of
fcNone: //Clear all flags
DCB.Flags := fBinary;
fcDefault:; //do nothing;
fcCTS:
DCB.Flags := DCB.Flags or fOutxCtsFlow or fRtsControlHandshake;
fcDTR:
DCB.Flags := DCB.Flags or fOutxDsrFlow or fDtrControlHandshake;
fcSoftware:
DCB.Flags := DCB.Flags or fOutX or fInX;
end;
end;
procedure Register;
begin
RegisterComponents('Varian Freeware', [TComm]);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -