const WM_COMMNOTIFY=WM_USER+1; //通信消息 type TForm1 = class(TForm) Label4: TLabel; RichEdit1: TRichEdit; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Label2: TLabel; Label1: TLabel; OpenDialog1: TOpenDialog; Button6: TButton; Memo1: TMemo; Label3: TLabel; Button7: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); procedure Button7Click(Sender: TObject); private { Private declarations } procedure WMCOMMNOTIFY(var Message:TMessage); message WM_COMMNOTIFY; public { Public declarations } end;var Form1: TForm1;implementation {$R *.dfm} var hNewCommFile,Post_Event:THandle; Read_os:Toverlapped; Receive:boolean; ReceiveData:Dword;//接收的数据送入显示区 procedure AddToMemo(str:PChar;len:Dword); begin str[len]:=#0; Form1.RichEdit1.Text:=Form1.RichEdit1.Text+strpas(str); end;//通信监视线程 procedure CommWatch(Ptr:Pointer);stdcall; var dwEvtMask,dwTranser:Dword; OK:boolean; Os:Toverlapped; begin Receive:=True; FillChar(Os,sizeof(Os),0); Os.hEvent:=CreateEvent(nil,true,false,nil); //创建重叠读事件对象 if os.hEvent=null then begin MessageBox(0,'Os.Event Creat Erro!','Notice',MB_OK); exit; end; if(not SetCommMask(hNewCommFile,EV_RXCHAR)) then begin MessageBox(0,'SetCommMask Error!','Notice',MB_OK); exit; end; while(Receive) do begin dwEvtMask:=0; //等待设置好的通信事件发生,由于有个Os(Os:Toverlapped),表示 //进行的是overlapped等待,不会被这个等待堵塞住 if not WaitCommEvent(hNewCommFile,dwEvtMask,@Os) then begin if ERROR_IO_PENDING=GetLastError then GetOverLappedResult(hNewCommFile,Os,dwTranser,True) end; if ((dwEvtMask and EV_RXCHAR)=EV_RXCHAR) then begin WaitForSingleObject(Post_event,INFINITE); //等待允许传递WM_COMMNOTIFY通信消息 ResetEvent(Post_Event); //处理WM_COMMNOTIFY消息,不再发生WM_COMMNOTIFY消息 OK:=PostMessage(Form1.Handle,WM_COMMNOTIFY,hNewCommFile,0); //传递WM_COMMNOTIFY通信消息 if(not OK) then begin MessageBox(0,'PostMessage Error!','Notice',MB_OK); exit; end; end; end; CloseHandle(Os.hEvent); end; { TForm1 } //消息处理函数 procedure TForm1.WMCOMMNOTIFY(var Message: TMessage); var CommState:ComStat; dwNumberOfBytesRead:Dword; ErrorFlag:Dword; InputBuffer:array[0..1024] of char; begin //ClearCommError回复通信错误信息并报告当前的通信设备状态。当通信错误发生 //时调用此函数,他会清除附加的I/O操作的设备错误标志 if not ClearCommError(hNewCommFile,ErrorFlag,@CommState) then begin MessageBox(0,'ClearcommErro!','Notice',MB_OK); PurgeComm(hNewCommFile,Purge_Rxabort or Purge_Rxclear); exit; end; if(Commstate.cbInQue >0) then begin fillchar(InputBuffer,CommState.cbInQue,#0); //接收通信数据 if(not ReadFile(hNewCommFile,InputBuffer,CommState.cbInQue, dwNumberOfBytesRead,@Read_Os)) then begin ErrorFlag:=GetLastError(); if(ErrorFlag<>0) and (ErrorFlag<>ERROR_IO_PENDING) then begin MessageBox(0,'ReadFile Error!','Notice',MB_OK); Receive:=False; CloseHandle(Read_Os.hEvent); CloseHandle(Post_Event); CloseHandle(hNewCommFile); exit; end else begin WaitForSingleObject(hNewCommFile,INFINITE); //等待操作完成,等待设置好的Event的发送 GetOverlappedResult(hNewCommFile,Read_Os, dwNumberOfBytesRead,false); end; end; if dwNumberOfBytesRead>0 then begin Read_Os.Offset:=Read_Os.Offset+dwNumberOfBytesRead; ReceiveData:=Read_Os.Offset ; AddToMemo(InputBuffer,dwNumberOfBytesRead); //处理接收的数据 end; end; SetEvent(Post_Event); //允许发送下一个WM_COMMNOTIFY消息 end;//打开文件用于发送 procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin Button3.Enabled:=false; button4.Enabled:=false; richedit1.Lines.LoadFromFile(OpenDialog1.FileName ); form1.Caption:=IntToStr(Richedit1.GetTextLen); end; button1.Enabled:=false; end;
接上: //发送数据 procedure TForm1.Button2Click(Sender: TObject); var dcb:TDCB; Error:boolean; dwNumberOfBytesWritten,dwNumberOfBytesToWrite,ErrorFlag, dwWhereToStartWriting:DWORD; pDataToWrite:PChar; Write_Os:Toverlapped; begin form1.Caption:=''; hNewCommFile:=CreateFile('COM1',GENERIC_WRITE,0,nil,OPEN_EXISTING, FILE_FLAG_OVERLAPPED,0); //打开通信端口com5 if hNewCommFile=INVALID_HANDLE_VALUE then MessageBox(0,'Error opening com port!','Notice',MB_OK); //设置缓冲区大小及主要通信参数 SetupComm(hNewCommFile,1024,1024); GetCommState(hNewCommFile,dcb); //设置com口的data control block 的属性 dcb.BaudRate:=9600; dcb.ByteSize:=8; dcb.Parity:=NOPARITY; dcb.StopBits:=ONESTOPBIT; Error:=SetCommState(hNewCommFile,dcb); if (not Error) then MessageBox(0,'SetCommState Error!','Notice',MB_OK); dwWhereToStartWriting:=0; dwNumberOfBytesWritten:=0; dwNumberofBytesToWrite:=richedit1.GetTextLen; if(dwNumberOfBytesToWrite=0) then begin ShowMessage('Text Buffer is Empty!'); exit; end else begin pDataToWrite:=StrAlloc(dwNumberOfBytesToWrite+1); try richedit1.GetTextBuf(pDataToWrite,dwNumberOfBytesToWrite); //label1.Font.Color:=clread; fillchar(Write_Os,sizeof(Write_Os),0); //为重叠写创建事件对象 Write_Os.hEvent:=CreateEvent(nil,True,False,nil); SetCommMask(hNewCommFile,EV_TXEMPTY); //用来表示对EV_TXEMPTY事件感兴趣,有char来到的时候系统会通知 label1.Caption:='正在发送数据...!'; repeat label1.Repaint; //发送通信数据 if not WriteFile(hNewCommFile,pDataToWrite[dwWhereToStartWriting], dwNumberOfBytesToWrite,dwNumberOfBytesWritten,@Write_Os) then begin ErrorFlag:=GetLastError; if ErrorFlag<>0 then begin if ErrorFlag=ERROR_IO_PENDING then begin //等待设置好的Event的发生 WaitForSingleObject(Write_Os.hEvent,INFINITE); GetOverlappedResult(hNewCommFile,Write_Os,dwNumberOfBytesWritten,false); end else begin MessageBox(0,'WriteFile Error!','Notice',MB_OK); Receive:=false; CloseHandle(Read_Os.hEvent); CloseHandle(Post_Event); CloseHandle(hNewCommFile); exit; end; end; end; Dec(dwNumberOfBytesToWrite,dwNumberOfBytesWritten); Inc(dwWhereToStartWriting,dwNumberOfBytesWritten); //写整个事情 until(dwNumberOfBytesToWrite<=0); Form1.Caption:=inttostr(dwWhereToStartWriting); finally strDispose(pDataToWrite); end; closeHandle(hNewCommFile); end; Label1.font.color:=clBlack; label1.caption:='发送成功!'; button1.enabled:=true; button3.enabled:=true; button4.enabled:=true; end;//接收处理 procedure TForm1.Button3Click(Sender: TObject); var Ok:boolean; dcb:TDCB; com_thread:Thandle; ThreadId:DWORD; begin ReceiveData:=0; Button1.Enabled:=false; button2.Enabled:=false; richedit1.Clear; //open com2 hNewCommFile:=CreateFile('COM2',GENERIC_READ,0,nil,OPEN_EXISTING, FILE_FLAG_OVERLAPPED,0); if hNewCommFile=INVALID_HANDLE_VALUE then begin MessageBox(0,'open com error','Notice',MB_OK); exit; end; //指定串行口事件为接收到字符 OK:=SetCommMask(hNewCommFile,EV_RXCHAR); if (not OK) then begin MessageBox(0,'SetCommMask Error!','Notice',MB_OK); exit; end; //设置缓冲区大小及主要通信参数 setupComm(hNewCommFile,1024,1024); GetCommState(hNewCommFile,dcb); dcb.BaudRate:=9600; dcb.ByteSize:=8; dcb.Parity:=NOPARITY; dcb.StopBits:=ONESTOPBIT; OK:= SetCommState(hNewCommFile,dcb); if(not Ok) then MessageBox(0,'SetCommState Error!','Notice',MB_OK); fillchar(Read_Os,sizeof(Read_Os),0); Read_Os.Offset:=0; Read_Os.OffsetHigh:=0; //创建overlapped read 事件 Read_Os.hEvent:=CreateEvent(nil,true,false,nil); if Read_os.hEvent =null then begin CloseHandle(hNewCommFile); MessageBox(0,'CreateEvent Error!','Notice',MB_OK); exit; end; //创建PostMessage事件 Post_Event:=CreateEvent(nil,true,true,nil); if Post_Event=null then begin CloseHandle(hNewCommFile); closeHandle(Read_Os.hEvent); messageBox(0,'CreateEvent Error','Notice',MB_OK); exit; end; Com_Thread:=CreateThread(nil,0,@CommWatch,nil,0,ThreadID); //建立通信监视线程 if(Com_Thread=0) then MessageBox(Handle,'CreateThread 函数不起作用!','Notice',MB_OK); EscapeCommFunction(hNewCommFile,SETDTR); label1.Font.Color:=clred; label1.Caption:='正在接收数据...'; end;//停止通信处理 procedure TForm1.Button4Click(Sender: TObject); begin label1.Font.Color:=clBlack; label1.Caption:='已停止通信'; form1.Caption:=inttostr(ReceiveData); Receive:=false;end;procedure TForm1.Button5Click(Sender: TObject); begin close; end;procedure TForm1.Button6Click(Sender: TObject); var reg : TRegistry; ts : TStrings; i : integer; begin reg := TRegistry.Create(); reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM\',false); ts := TStringList.Create(); reg.GetValueNames(ts); Memo1.Clear; for i := 0 to ts.Count -1 do begin Memo1.Lines.Add(reg.ReadString(ts.Strings[i])); end; ts.Free; reg.CloseKey; reg.free; end;procedure TForm1.Button7Click(Sender: TObject); begin while (1=1) do Label3.Caption :=inttostr(strtoint(Label3.Caption)+1); end;end.
http://soft.56kc.com/Filedown.aspx?FID=167
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls,Registry;
const
WM_COMMNOTIFY=WM_USER+1; //通信消息
type
TForm1 = class(TForm)
Label4: TLabel;
RichEdit1: TRichEdit;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Label2: TLabel;
Label1: TLabel;
OpenDialog1: TOpenDialog;
Button6: TButton;
Memo1: TMemo;
Label3: TLabel;
Button7: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
private
{ Private declarations }
procedure WMCOMMNOTIFY(var Message:TMessage);
message WM_COMMNOTIFY;
public
{ Public declarations }
end;var
Form1: TForm1;implementation
{$R *.dfm}
var
hNewCommFile,Post_Event:THandle;
Read_os:Toverlapped;
Receive:boolean;
ReceiveData:Dword;//接收的数据送入显示区
procedure AddToMemo(str:PChar;len:Dword);
begin
str[len]:=#0;
Form1.RichEdit1.Text:=Form1.RichEdit1.Text+strpas(str);
end;//通信监视线程
procedure CommWatch(Ptr:Pointer);stdcall;
var
dwEvtMask,dwTranser:Dword;
OK:boolean;
Os:Toverlapped;
begin
Receive:=True;
FillChar(Os,sizeof(Os),0);
Os.hEvent:=CreateEvent(nil,true,false,nil);
//创建重叠读事件对象
if os.hEvent=null then
begin
MessageBox(0,'Os.Event Creat Erro!','Notice',MB_OK);
exit;
end;
if(not SetCommMask(hNewCommFile,EV_RXCHAR)) then
begin
MessageBox(0,'SetCommMask Error!','Notice',MB_OK);
exit;
end;
while(Receive) do
begin
dwEvtMask:=0;
//等待设置好的通信事件发生,由于有个Os(Os:Toverlapped),表示
//进行的是overlapped等待,不会被这个等待堵塞住
if not WaitCommEvent(hNewCommFile,dwEvtMask,@Os) then
begin
if ERROR_IO_PENDING=GetLastError then
GetOverLappedResult(hNewCommFile,Os,dwTranser,True)
end;
if ((dwEvtMask and EV_RXCHAR)=EV_RXCHAR) then
begin
WaitForSingleObject(Post_event,INFINITE);
//等待允许传递WM_COMMNOTIFY通信消息
ResetEvent(Post_Event);
//处理WM_COMMNOTIFY消息,不再发生WM_COMMNOTIFY消息
OK:=PostMessage(Form1.Handle,WM_COMMNOTIFY,hNewCommFile,0);
//传递WM_COMMNOTIFY通信消息
if(not OK) then
begin
MessageBox(0,'PostMessage Error!','Notice',MB_OK);
exit;
end;
end;
end;
CloseHandle(Os.hEvent);
end;
{ TForm1 }
//消息处理函数
procedure TForm1.WMCOMMNOTIFY(var Message: TMessage);
var
CommState:ComStat;
dwNumberOfBytesRead:Dword;
ErrorFlag:Dword;
InputBuffer:array[0..1024] of char;
begin
//ClearCommError回复通信错误信息并报告当前的通信设备状态。当通信错误发生
//时调用此函数,他会清除附加的I/O操作的设备错误标志
if not ClearCommError(hNewCommFile,ErrorFlag,@CommState) then
begin
MessageBox(0,'ClearcommErro!','Notice',MB_OK);
PurgeComm(hNewCommFile,Purge_Rxabort or Purge_Rxclear);
exit;
end;
if(Commstate.cbInQue >0) then
begin
fillchar(InputBuffer,CommState.cbInQue,#0);
//接收通信数据
if(not ReadFile(hNewCommFile,InputBuffer,CommState.cbInQue,
dwNumberOfBytesRead,@Read_Os)) then
begin
ErrorFlag:=GetLastError();
if(ErrorFlag<>0) and (ErrorFlag<>ERROR_IO_PENDING) then
begin
MessageBox(0,'ReadFile Error!','Notice',MB_OK);
Receive:=False;
CloseHandle(Read_Os.hEvent);
CloseHandle(Post_Event);
CloseHandle(hNewCommFile);
exit;
end
else
begin
WaitForSingleObject(hNewCommFile,INFINITE);
//等待操作完成,等待设置好的Event的发送
GetOverlappedResult(hNewCommFile,Read_Os,
dwNumberOfBytesRead,false);
end;
end;
if dwNumberOfBytesRead>0 then
begin
Read_Os.Offset:=Read_Os.Offset+dwNumberOfBytesRead;
ReceiveData:=Read_Os.Offset ;
AddToMemo(InputBuffer,dwNumberOfBytesRead);
//处理接收的数据
end;
end;
SetEvent(Post_Event);
//允许发送下一个WM_COMMNOTIFY消息
end;//打开文件用于发送
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
Button3.Enabled:=false;
button4.Enabled:=false;
richedit1.Lines.LoadFromFile(OpenDialog1.FileName );
form1.Caption:=IntToStr(Richedit1.GetTextLen);
end; button1.Enabled:=false;
end;
//发送数据
procedure TForm1.Button2Click(Sender: TObject);
var
dcb:TDCB;
Error:boolean;
dwNumberOfBytesWritten,dwNumberOfBytesToWrite,ErrorFlag,
dwWhereToStartWriting:DWORD;
pDataToWrite:PChar;
Write_Os:Toverlapped;
begin
form1.Caption:='';
hNewCommFile:=CreateFile('COM1',GENERIC_WRITE,0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
//打开通信端口com5
if hNewCommFile=INVALID_HANDLE_VALUE then
MessageBox(0,'Error opening com port!','Notice',MB_OK); //设置缓冲区大小及主要通信参数
SetupComm(hNewCommFile,1024,1024); GetCommState(hNewCommFile,dcb);
//设置com口的data control block 的属性
dcb.BaudRate:=9600;
dcb.ByteSize:=8;
dcb.Parity:=NOPARITY;
dcb.StopBits:=ONESTOPBIT;
Error:=SetCommState(hNewCommFile,dcb);
if (not Error) then
MessageBox(0,'SetCommState Error!','Notice',MB_OK);
dwWhereToStartWriting:=0;
dwNumberOfBytesWritten:=0;
dwNumberofBytesToWrite:=richedit1.GetTextLen;
if(dwNumberOfBytesToWrite=0) then
begin
ShowMessage('Text Buffer is Empty!');
exit;
end
else
begin
pDataToWrite:=StrAlloc(dwNumberOfBytesToWrite+1);
try
richedit1.GetTextBuf(pDataToWrite,dwNumberOfBytesToWrite);
//label1.Font.Color:=clread;
fillchar(Write_Os,sizeof(Write_Os),0);
//为重叠写创建事件对象
Write_Os.hEvent:=CreateEvent(nil,True,False,nil);
SetCommMask(hNewCommFile,EV_TXEMPTY);
//用来表示对EV_TXEMPTY事件感兴趣,有char来到的时候系统会通知
label1.Caption:='正在发送数据...!';
repeat
label1.Repaint;
//发送通信数据
if not WriteFile(hNewCommFile,pDataToWrite[dwWhereToStartWriting],
dwNumberOfBytesToWrite,dwNumberOfBytesWritten,@Write_Os) then
begin
ErrorFlag:=GetLastError;
if ErrorFlag<>0 then
begin
if ErrorFlag=ERROR_IO_PENDING then
begin
//等待设置好的Event的发生
WaitForSingleObject(Write_Os.hEvent,INFINITE);
GetOverlappedResult(hNewCommFile,Write_Os,dwNumberOfBytesWritten,false);
end
else
begin
MessageBox(0,'WriteFile Error!','Notice',MB_OK);
Receive:=false;
CloseHandle(Read_Os.hEvent);
CloseHandle(Post_Event);
CloseHandle(hNewCommFile);
exit;
end;
end;
end;
Dec(dwNumberOfBytesToWrite,dwNumberOfBytesWritten);
Inc(dwWhereToStartWriting,dwNumberOfBytesWritten);
//写整个事情
until(dwNumberOfBytesToWrite<=0);
Form1.Caption:=inttostr(dwWhereToStartWriting);
finally
strDispose(pDataToWrite);
end;
closeHandle(hNewCommFile);
end;
Label1.font.color:=clBlack;
label1.caption:='发送成功!';
button1.enabled:=true;
button3.enabled:=true;
button4.enabled:=true;
end;//接收处理
procedure TForm1.Button3Click(Sender: TObject);
var
Ok:boolean;
dcb:TDCB;
com_thread:Thandle;
ThreadId:DWORD;
begin
ReceiveData:=0;
Button1.Enabled:=false;
button2.Enabled:=false;
richedit1.Clear;
//open com2
hNewCommFile:=CreateFile('COM2',GENERIC_READ,0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if hNewCommFile=INVALID_HANDLE_VALUE then
begin
MessageBox(0,'open com error','Notice',MB_OK);
exit;
end; //指定串行口事件为接收到字符
OK:=SetCommMask(hNewCommFile,EV_RXCHAR);
if (not OK) then
begin
MessageBox(0,'SetCommMask Error!','Notice',MB_OK);
exit;
end;
//设置缓冲区大小及主要通信参数
setupComm(hNewCommFile,1024,1024);
GetCommState(hNewCommFile,dcb);
dcb.BaudRate:=9600;
dcb.ByteSize:=8;
dcb.Parity:=NOPARITY;
dcb.StopBits:=ONESTOPBIT;
OK:= SetCommState(hNewCommFile,dcb);
if(not Ok) then
MessageBox(0,'SetCommState Error!','Notice',MB_OK);
fillchar(Read_Os,sizeof(Read_Os),0);
Read_Os.Offset:=0;
Read_Os.OffsetHigh:=0;
//创建overlapped read 事件
Read_Os.hEvent:=CreateEvent(nil,true,false,nil);
if Read_os.hEvent =null then
begin
CloseHandle(hNewCommFile);
MessageBox(0,'CreateEvent Error!','Notice',MB_OK);
exit;
end;
//创建PostMessage事件
Post_Event:=CreateEvent(nil,true,true,nil);
if Post_Event=null then
begin
CloseHandle(hNewCommFile);
closeHandle(Read_Os.hEvent);
messageBox(0,'CreateEvent Error','Notice',MB_OK);
exit;
end;
Com_Thread:=CreateThread(nil,0,@CommWatch,nil,0,ThreadID);
//建立通信监视线程
if(Com_Thread=0) then
MessageBox(Handle,'CreateThread 函数不起作用!','Notice',MB_OK);
EscapeCommFunction(hNewCommFile,SETDTR);
label1.Font.Color:=clred;
label1.Caption:='正在接收数据...';
end;//停止通信处理
procedure TForm1.Button4Click(Sender: TObject);
begin
label1.Font.Color:=clBlack;
label1.Caption:='已停止通信';
form1.Caption:=inttostr(ReceiveData);
Receive:=false;end;procedure TForm1.Button5Click(Sender: TObject);
begin
close;
end;procedure TForm1.Button6Click(Sender: TObject);
var
reg : TRegistry;
ts : TStrings;
i : integer;
begin
reg := TRegistry.Create();
reg.RootKey := HKEY_LOCAL_MACHINE;
reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM\',false);
ts := TStringList.Create();
reg.GetValueNames(ts);
Memo1.Clear;
for i := 0 to ts.Count -1 do
begin
Memo1.Lines.Add(reg.ReadString(ts.Strings[i]));
end;
ts.Free;
reg.CloseKey;
reg.free;
end;procedure TForm1.Button7Click(Sender: TObject);
begin
while (1=1) do
Label3.Caption :=inttostr(strtoint(Label3.Caption)+1);
end;end.