⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spcomm.pas.~8~

📁 其中包含XPMenu控件和SPComm控件
💻 ~8~
📖 第 1 页 / 共 5 页
字号:
** Author:    Administrator** Date:      23-七月-2007** Arguments: None** Result:    None** PURPOSE: Close the Read Thread.** PARAMETERS:  none
** RETURN VALUE:  none
** COMMENTS:
**   Closes the Read thread by signaling the CloseEvent.
**   Purges any outstanding reads on the comm port.
** Note that terminating a thread leaks memory.
**   Besides the normal leak incurred, there is an event object
**   that doesn't get closed.  This isn't worth worrying about
**   since it shouldn't happen anyway.
****************************************************************************}
procedure TComm.CloseReadThread;
begin
  // If it exists...
  if ReadThread <> nil then
  begin
    // Signal the event to close the worker threads.
    SetEvent( hCloseEvent );

    // Purge all outstanding reads
    PurgeComm( hCommFile, PURGE_RXABORT + PURGE_RXCLEAR );

    // Wait 10 seconds for it to exit.  Shouldn't happen.
    if (WaitForSingleObject(ReadThread.Handle, 10000) = WAIT_TIMEOUT) then
       ReadThread.Terminate;
    ReadThread.Free;
    ReadThread := nil
  end
end; {TComm.CloseReadThread}


{****************************************************************************
** Procedure: CloseWriteThread** Author:    Administrator** Date:      23-七月-2007** Arguments: None** Result:    None** PURPOSE: Closes the Write Thread.** PARAMETERS: none
** RETURN Value: none
** COMMENTS:
**   Closes the write thread by signaling the CloseEvent.
**   Purges any outstanding writes on the comm port.
** Note that terminating a thread leaks memory.
**   Besides the normal leak incurred, there is an event object
**   that doesn't get closed.  This isn't worth worrying about
**   since it shouldn't happen anyway.
****************************************************************************}
procedure TComm.CloseWriteThread;
begin
  // If it exists...
  if WriteThread <> nil then
  begin
    // Signal the event to close the worker threads.
    SetEvent(hCloseEvent);

    // Purge all outstanding writes.
    PurgeComm(hCommFile, PURGE_TXABORT + PURGE_TXCLEAR);
    FSendDataEmpty := True;

    // Wait 10 seconds for it to exit.  Shouldn't happen.
    if WaitForSingleObject( WriteThread.Handle, 10000 ) = WAIT_TIMEOUT then
       WriteThread.Terminate;
    WriteThread.Free;
    WriteThread := nil
  end
end; {TComm.CloseWriteThread}

procedure TComm.CloseRWThread;
begin
  CloseReadThread;
  CloseWriteThread;
end;

(****************************************************************************
 * 函数:   CreateAndStartRWThread(None);
 * 功能:   创建读写线程并启动.
 * 作者:   Administrator
 * 日期:   2007-09-25
 * 参数:   None
 * 返回值: None
 * 描述:
 ****************************************************************************)
procedure TComm.CreateAndStartRWThread;
begin
  // Create the Read thread.
  if ReadThread=nil then
  begin
    try
       ReadThread := TReadThread.Create( True {suspended} );
    except
          ReadThread := nil;
          CloseHandle( hCloseEvent );
          CloseHandle( hCommFile );
          hCommFile := 0;
          raise ECommsError.Create( 'Unable to create read thread' )
    end;
  end;
  ReadThread.hCommFile := hCommFile;
  ReadThread.hCloseEvent := hCloseEvent;
  ReadThread.hComm32Window := FHWnd;

  // Comm threads should have a higher base priority than the UI thread.
  // If they don't, then any temporary priority boost the UI thread gains
  // could cause the COMM threads to loose data.
  ReadThread.Priority := tpHighest;

  // Create the Write thread.
  if WriteThread=nil then
  begin
    try
       WriteThread := TWriteThread.Create( True {suspended} );
    except
          CloseReadThread;
          WriteThread := nil;
          CloseHandle( hCloseEvent );
          CloseHandle( hCommFile );
          hCommFile := 0;
          raise ECommsError.Create( 'Unable to create write thread' )
    end;
  end;
  WriteThread.hCommFile := hCommFile;
  WriteThread.hCloseEvent := hCloseEvent;
  WriteThread.hComm32Window := FHWnd;
  WriteThread.pFSendDataEmpty := @FSendDataEmpty;

  WriteThread.Priority := tpHigher;

  ReadThread.Resume;
  WriteThread.Resume;
end;

procedure TComm.ReceiveData(Buffer: PChar; BufferLength: Word);
begin
  if Assigned(FOnReceiveData) then
    FOnReceiveData( self, Buffer, BufferLength )
end;

procedure TComm.ReceiveError( EvtMask : DWORD );
begin
  if Assigned(FOnReceiveError) then
    FOnReceiveError( self, EvtMask )
end;

procedure TComm.ModemStateChange( ModemEvent : DWORD );
begin
  if Assigned(FOnModemStateChange) then
    FOnModemStateChange( self, ModemEvent )
end;

procedure TComm.RequestHangup;
begin
  if Assigned(FOnRequestHangup) then
    FOnRequestHangup( Self )
end;

procedure TComm._SendDataEmpty;
begin
  if Assigned(FOnSendDataEmpty) then
    FOnSendDataEmpty( self )
end;

(******************************************************************************)
//  TComm PRIVATE METHODS
(******************************************************************************)

procedure TComm.CommWndProc( var msg: TMessage );
begin
  case msg.msg of
    PWM_GOTCOMMDATA:
    begin
      ReceiveData( PChar(msg.LParam), msg.WParam );
      LocalFree( msg.LParam );
    end;
    PWM_RECEIVEERROR:    ReceiveError( msg.LParam );
    PWM_MODEMSTATECHANGE:ModemStateChange( msg.LParam );
    PWM_REQUESTHANGUP:   RequestHangup;
    PWM_SENDDATAEMPTY:   _SendDataEmpty
  end
end;

procedure TComm._SetCommState;
var
  dcb:            Tdcb;
  commprop:       TCommProp;
  fdwEvtMask:     DWORD;
begin
  // Configure the comm settings.
  // NOTE: Most Comm settings can be set through TAPI, but this means that
  //       the CommFile will have to be passed to this component.

  GetCommState( hCommFile, dcb );
  GetCommProperties( hCommFile, commprop );
  GetCommMask( hCommFile, fdwEvtMask );

  // fAbortOnError is the only DCB dependancy in TapiComm.
  // Can't guarentee that the SP will set this to what we expect.
  {dcb.fAbortOnError := False; NOT VALID}

  dcb.BaudRate := FBaudRate;

  dcb.Flags := 1;         // Enable fBinary

  if FParityCheck then
     dcb.Flags := dcb.Flags or 2;          // Enable parity check

  // setup hardware flow control

  if FOutx_CtsFlow then
     dcb.Flags := dcb.Flags or 4;

  if FOutx_DsrFlow then
     dcb.Flags := dcb.Flags or 8;

  if FDtrControl = DtrEnable then
     dcb.Flags := dcb.Flags or $10
  else if FDtrControl = DtrHandshake then
       dcb.Flags := dcb.Flags or $20;

  if FDsrSensitivity then
     dcb.Flags := dcb.Flags or $40;

  if FTxContinueOnXoff then
     dcb.Flags := dcb.Flags or $80;

  if FOutx_XonXoffFlow then
     dcb.Flags := dcb.Flags or $100;

  if FInx_XonXoffFlow then
     dcb.Flags := dcb.Flags or $200;

  if FReplaceWhenParityError then
     dcb.Flags := dcb.Flags or $400;

  if FIgnoreNullChar then
     dcb.Flags := dcb.Flags or $800;

  if FRtsControl = RtsEnable then
     dcb.Flags := dcb.Flags or $1000
  else if FRtsControl = RtsHandshake then
       dcb.Flags := dcb.Flags or $2000
  else if FRtsControl = RtsTransmissionAvailable then
       dcb.Flags := dcb.Flags or $3000;

  dcb.XonLim := FXonLimit;
  dcb.XoffLim := FXoffLimit;

  dcb.ByteSize := Ord( FByteSize ) + 5;
  dcb.Parity := Ord( FParity );
  dcb.StopBits := Ord( FStopBits );

  dcb.XonChar := FXonChar;
  dcb.XoffChar := FXoffChar;

  dcb.ErrorChar := FReplacedChar;

  SetCommState( hCommFile, dcb )
end;

(****************************************************************************
 * 函数:   _SetCommTimeout(None);
 * 功能:   
 * 作者:   Administrator
 * 日期:   2007-09-26
 * 参数:   None
 * 返回值: None
 * 描述:
    TCommTimeouts 结构参数意义:
      ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,
        一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。
        设置为0表示该参数不起作用。
      ReadTotalTimeoutMultiplier:读取每字符间的超时。
      ReadTotalTimeoutConstant:一次读取串口数据的固定超时。
      WriteTotalTimeoutMultiplier:写入每字符间的超时。
      WriteTotalTimeoutConstant:一次写入串口数据的固定超时。
  所以:
     在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数
  再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将
  ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将
  立即返回存放在输入缓冲区的字符。
    在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数
    再加上 WriteTotalTimeoutConstant。
 ****************************************************************************)
procedure TComm._SetCommTimeout;
var
  commtimeouts:   TCommTimeouts;
begin
  GetCommTimeouts( hCommFile, commtimeouts );

  // The CommTimeout numbers will very likely change if you are
  // coding to meet some kind of specification where
  // you need to reply within a certain amount of time after
  // recieving the last byte.  However,  If 1/4th of a second
  // goes by between recieving two characters, its a good
  // indication that the transmitting end has finished, even
  // assuming a 1200 baud modem.

  commtimeouts.ReadIntervalTimeout         := FReadIntervalTimeout;
  commtimeouts.ReadTotalTimeoutMultiplier  := FReadTotalTimeoutMultiplier;
  commtimeouts.ReadTotalTimeoutConstant    := FReadTotalTimeoutConstant;
  commtimeouts.WriteTotalTimeoutMultiplier := FWriteTotalTimeoutMultiplier;
  commtimeouts.WriteTotalTimeoutConstant   := FWriteTotalTimeoutConstant;

  SetCommTimeouts( hCommFile, commtimeouts );
end;

procedure TComm.SetBaudRate( Rate : DWORD );
begin
  if Rate = FBaudRate then
    Exit;

  FBaudRate := Rate;

  if hCommFile <> 0 then
    _SetCommState
end;

procedure TComm.SetParityCheck( b : Boolean );
begin
  if b = FParityCheck then
    Exit;

  FParityCheck := b;

  if hCommFile <> 0 then
    _SetCommState
end;

procedure TComm.SetOutx_CtsFlow( b : Boolean );
begin
  if b = FOutx_CtsFlow then
    Exit;

  FOutx_CtsFlow := b;

  if hCommFile <> 0 then
    _SetCommState
end;

procedure TComm.SetOutx_DsrFlow( b : Boolean );
begin
     if b = FOutx_DsrFlow then
        Exit;

     FOutx_DsrFlow := b;

     if hCommFile <> 0 then
        _SetCommState
end;

procedure TComm.SetDtrControl( c : TDtrControl );
begin
     if c = FDtrControl then
        Exit;

     FDtrControl := c;

     if hCommFile <> 0 then
        _SetCommState

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -