?? exportfrm.pas
字號(hào):
{
=====================================================================
* 軟件名稱:PC與數(shù)控機(jī)床通信程序
* 單元名稱:發(fā)送數(shù)據(jù)到數(shù)控機(jī)床
* 單元作者:彭為 (pwzyp@fjsm.net)
* 備 注:用到了線程進(jìn)行發(fā)送
* 開發(fā)平臺(tái):PWin2000 SERVER + Delphi 7.0
* 兼容測(cè)試:PWin9X/2000/XP + Delphi 6/7
* 采用控件:Raize 3.12 ,SPCOMM
* 修改記錄:V1.0 by pengwei
=====================================================================
}
unit ExportFrm; //本單元用來(lái)發(fā)送數(shù)據(jù)
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, jpeg, ExtCtrls, RzTabs, RzButton, StdCtrls, RzLabel, RzBorder,
Grids, ValEdit, RzPrgres, ScktComp, SPComm, DB, ADODB;
type
TExportData = class(TForm)
Panel1: TPanel;
pgcMain: TRzPageControl;
TabSheet1: TRzTabSheet;
TabSheet2: TRzTabSheet;
Image1: TImage;
Panel2: TPanel;
btnFinish: TRzBitBtn;
btnNext: TRzBitBtn;
btnPrior: TRzBitBtn;
RzLabel1: TRzLabel;
RzLabel2: TRzLabel;
RzLabel3: TRzLabel;
Image2: TImage;
RzBorder1: TRzBorder;
RzLabel4: TRzLabel;
RzLabel5: TRzLabel;
RzLabel6: TRzLabel;
edtUser: TEdit;
edtMemo: TEdit;
TabSheet3: TRzTabSheet;
Image4: TImage;
RzLabel12: TRzLabel;
RzBorder3: TRzBorder;
Lbl1: TRzLabel;
Lbl2: TRzLabel;
Lbl3: TRzLabel;
pgb1: TRzProgressBar;
Lbl4: TRzLabel;
LblErr: TRzLabel;
Lbl5: TRzLabel;
RzLabel7: TRzLabel;
RzLabel8: TRzLabel;
cboChannel: TComboBox;
RzBorder4: TRzBorder;
RzLabel9: TRzLabel;
cboComm: TComboBox;
Comm1: TComm;
Query: TADOQuery;
LblCommErr: TRzLabel;
procedure FormCreate(Sender: TObject); //界面初始化代碼
procedure btnNextClick(Sender: TObject); //“下一步”按鈕點(diǎn)擊事件
procedure btnPriorClick(Sender: TObject); //“上一步”按鈕點(diǎn)擊事件
procedure btnFinishClick(Sender: TObject); //“完成”按鈕點(diǎn)擊事件
procedure cboChannelEnter(Sender: TObject); //用戶改變“設(shè)備”的事件
procedure FormDestroy(Sender: TObject); //銷毀對(duì)象時(shí)執(zhí)行
procedure Comm1ReceiveError(Sender: TObject; EventMask: Cardinal); //SPCOMM接收數(shù)據(jù)錯(cuò)誤事件
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word); //SPCOMM接收數(shù)據(jù)事件(很關(guān)鍵)
procedure FormShow(Sender: TObject);
private
Fid: Integer; //局部變量存放ID
Channel: Integer; //
SendText: Tstrings; //發(fā)送的內(nèi)容(數(shù)據(jù)機(jī)床命令,存在TSTRINGS對(duì)象中)
{ Private declarations }
public
bStart: Boolean; //是否已開始發(fā)送標(biāo)志(用于線程與主界面同步)
TickCount: Longword; //機(jī)床號(hào)
procedure showForm(const id: integer);
constructor Create(const id: Integer); reintroduce; overload;
{ Public declarations }
end;
//發(fā)送數(shù)據(jù)的線程,系統(tǒng)啟動(dòng)發(fā)送后,其它的回復(fù)等由該線程進(jìn)行
TSendThread = class(TThread)
private
Pos, Len: LongWord; //當(dāng)前位置,總長(zhǎng)度
CurrChar: Char; // 當(dāng)前發(fā)送的字符
FSendText: string; //全部長(zhǎng)度
procedure Ok; //發(fā)送完成后執(zhí)行的過(guò)程
procedure Percent; //顯示百分比過(guò)程
public
constructor Create(SendText: string); //線程的構(gòu)造過(guò)程
procedure Execute; override; //線程的執(zhí)行體
end;
var
ExportData: TExportData;
SendThread: TSendThread;
implementation
uses Include, Mainfrm, ConfigFrm;
{$R *.dfm}
procedure TExportData.FormCreate(Sender: TObject);
begin
Caption := sExportCaption; //sExportCaption是窗口名'發(fā)送數(shù)據(jù)至數(shù)控機(jī)床'
SendText := TStringlist.Create; //構(gòu)造臨時(shí)變量
end;
procedure TExportData.btnNextClick(Sender: TObject);
var
FileName, sTemp: string;
BeginChar: Byte; //初始標(biāo)志位
BeginChannel: array[1..2] of Byte; //2位字節(jié)數(shù)組
begin
case pgcmain.activepageindex of
0: //如果是第一頁(yè)
begin
//初始化第二頁(yè)的控件
//清空機(jī)床的列表框
cboChannel.Clear;
cboChannel.Items := Config.ChannelList;
//從數(shù)據(jù)庫(kù)中查詢出要發(fā)送的文件的內(nèi)容
with Query do
begin
Close;
SQL.Clear;
SQL.Add('Select * from Data where id=' + IntToStr(Fid));
Open;
FileName := FieldByName('filename').AsString;
if FileExists(FileName) then //如果文件存在的話
begin
Application.ProcessMessages;
SendText.LoadFromFile(FileName);
//如果內(nèi)容是空的
if Trim(SendText.Text) = '' then
begin
MessageBox(Self.Handle, PChar(sFileEmpty), PChar(sTitleErr), MB_OK
+
MB_ICONERROR);
exit;
end;
end
else
begin //如果文件不存在
MessageBox(Self.Handle, PChar(sNotFile), PChar(sTitleErr), MB_OK +
MB_ICONERROR);
exit;
end;
//初始化必要的信息
edtUser.Text := FieldByName('Author').AsString;
edtMemo.Text := FieldByName('sMemo').AsString;
Channel := FieldByName('Channel').AsInteger;
cboChannel.ItemIndex := Channel - 1;
cboComm.ItemIndex := cboComm.Items.IndexOf(Config.CommName);
Close;
end;
LblCommErr.Visible := False;
end;
1: //如果是第二頁(yè)
begin
//初始化發(fā)送前的準(zhǔn)備工作
Config.CommName := cboComm.Text; //串口
Channel := cboChannel.ItemIndex + 1; //機(jī)床號(hào)
//啟動(dòng)SPCOMM控件COMM1
Comm1.CommName := Config.CommName;
//先關(guān)閉
Comm1.StopComm;
try
//再打開
Comm1.StartComm;
except
//捕獲異常
LblCommErr.Visible := True;
Exit;
end;
//起始字節(jié)為01,具體請(qǐng)參看通訊協(xié)議
BeginChar := 01;
//把機(jī)床號(hào)變成2位的ASCII碼
sTemp := Format('%.2d', [channel]);
//把它的ASCII值送到臨時(shí)數(shù)組中去
BeginChannel[1] := Ord(sTemp[1]);
BeginChannel[2] := Ord(sTemp[2]);
// ShowMessage(Format('%x %x %x', [beginchar[1], beginchar[2],beginchar[3]]));
Sleep(100); //如果不休眠100毫秒,可能會(huì)發(fā)生錯(cuò)誤,因?yàn)榇蜷_串口需要時(shí)間,以下類同
Comm1.WriteCommData(@BeginChar, 1); //用SPCOMM往端口發(fā)送啟始位01H
Sleep(100);
Comm1.WriteCommData(@BeginChannel, 2); //用SPCOMM發(fā)送機(jī)床號(hào)(選床)
//開始發(fā)送正式的數(shù)據(jù)標(biāo)志置FALSE
bStart := False;
//界面代碼,使界面上的字變粗顯示表示當(dāng)前進(jìn)度
Lbl1.Font.Style := [fsBold];
Lbl2.Font.Style := [fsBold];
Lbl3.Font.Style := [];
Lbl4.Font.Style := [];
Lbl5.Visible := False;
LblErr.Visible := False;
pgb1.Percent := 0;
end;
else
;
end;
//轉(zhuǎn)下一頁(yè)
pgcMain.ActivePageIndex := pgcMain.ActivePageIndex + 1;
btnPrior.Enabled := True;
if pgcMain.ActivePageIndex = pgcMain.PageCount - 1 then
btnNext.Enabled := False;
end;
procedure TExportData.btnPriorClick(Sender: TObject);
begin
//轉(zhuǎn)前一頁(yè)
pgcMain.ActivePageIndex := pgcMain.ActivePageIndex - 1;
btnNext.Enabled := True;
if pgcMain.ActivePageIndex = 0 then
btnPrior.Enabled := False;
end;
procedure TExportData.showForm(const id: integer);
begin
//顯示窗體的函數(shù)(實(shí)際調(diào)用時(shí)用本函數(shù)即可)
if ExportData = nil then
ExportData := TExportData.Create(id);
ExportData.ShowModal;
end;
procedure TExportData.btnFinishClick(Sender: TObject);
begin
//點(diǎn)擊了完成 或取消
if bStart then
begin
// 如果正在發(fā)送,則關(guān)閉線程
bStart := False;
SendThread.Terminate;
//中斷發(fā)送數(shù)據(jù)線程
end;
//關(guān)閉串口
Comm1.StopComm;
Close;
end;
procedure TExportData.cboChannelEnter(Sender: TObject);
begin
LblCommErr.Visible := False;
end;
procedure TExportData.FormDestroy(Sender: TObject);
begin
//釋放內(nèi)存
SendText.Free;
end;
procedure TExportData.Comm1ReceiveError(Sender: TObject;
EventMask: Cardinal);
begin
LblErr.Caption := '串口接收數(shù)據(jù)出現(xiàn)錯(cuò)誤';
LblErr.Visible := True;
end;
procedure TExportData.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
ReceivedBuf: array of Byte;
stemp: string;
BeginChar: array[1..2] of Byte;
SendChar: Byte;
i: Integer;
begin
SetLength(ReceivedBuf, BufferLength);
try
//把接收到的字符放入BUFFER
Move(Buffer^, Pchar(@ReceivedBuf[0])^, BufferLength);
except
ShowMsg(sErrReceive1);
exit;
end;
if not bStart then
begin //尚未開始,根據(jù)協(xié)議,接收到的應(yīng)該就是具體的機(jī)床號(hào)與前面的機(jī)床號(hào)相同
stemp := Format('%.2d', [Channel]);
BeginChar[1] := Ord(sTemp[1]);
BeginChar[2] := Ord(sTemp[2]);
if ((ReceivedBuf[0] = BeginChar[1]) and (ReceivedBuf[1] = BeginChar[2])) then
begin //床號(hào)正確//開始回發(fā)床號(hào),并發(fā)數(shù)據(jù) 置start為True
//根據(jù)協(xié)議,02H為發(fā)送數(shù)據(jù)的功能
SendChar := 02;
Comm1.WriteCommData(@SendChar, 1);
bstart := True;
//發(fā)數(shù)據(jù)
Lbl3.Font.Style := [fsBold];
pgb1.Percent := 0;
//啟動(dòng)數(shù)據(jù)發(fā)送線程
SendThread := TSendThread.Create(SendText.Text);
end
else
begin //床號(hào)不正確,顯示錯(cuò)誤并返回
LblErr.Caption := '設(shè)備號(hào)選擇出錯(cuò)!';
LblErr.Visible := True;
end;
end
else
//其它情況正在正在發(fā)送,檢測(cè)是否是07H(錯(cuò)誤)
//設(shè)置停止標(biāo)志終止線程的發(fā)送
for i := 0 to BufferLength - 1 do
begin
if ReceivedBuf[i] = $07 then
begin
bStart := false;
SendThread.Terminate;
LblErr.Caption := '數(shù)控機(jī)床設(shè)備返回錯(cuò)誤信息,終止發(fā)送!';
LblErr.Visible := True;
Exit;
end
else if ReceivedBuf[i] = $17 then //完成了
begin
bStart := False;
pgb1.Percent := 100;
Lbl4.Font.Style := [fsbold];
Lbl5.Caption := '花費(fèi)時(shí)間:' + IntToStr(GetTickCount - TickCount) +
'毫秒';
btnFinish.Caption := '完成';
Exit;
end;
end;
end;
{ TSendThread }
constructor TSendThread.Create(SendText: string);
begin
//線程的構(gòu)造線程
FSendText := Copy(SendText, 1, Length(SendText) - 2);
inherited Create(False);
end;
procedure TSendThread.Execute;
var
isSend: Boolean;
begin
FreeOnTerminate := True; //控制線程空閑時(shí)自動(dòng)中斷
ExportData.TickCount := GetTickCount; //時(shí)間戳(用來(lái)計(jì)算發(fā)送時(shí)間)
if not TestEOF(FSendText) then //如果沒(méi)有結(jié)束符加入結(jié)束符
//TESTEOF的函數(shù)在INCLUDE單元中定義,請(qǐng)查看所有源代碼
FSendText := FSendText + Chr(26);
//開始發(fā)送之前記載發(fā)送的總長(zhǎng)度
Len := Length(FSendtext);
//當(dāng)前位置是第一個(gè)字符
Pos := 1;
//當(dāng)發(fā)送數(shù)據(jù)未完而且主窗口的bstart為True則發(fā)送(如果主界面要取消,只要置bstart為false即可)
while (Pos <= Len) and ExportData.bstart do
begin
//檢查是否發(fā)送該字節(jié)
isSend := True;
CurrChar := FSendText[pos];
case CurrChar of
'a'..'z': CurrChar := UpperCase(CurrChar)[1];
'A'..'Z', '0'..'9', '+', '-', '/', '.', Chr(26), '%', Chr(00), Chr($0A): ;
else
isSend := False;
end;
if isSend then
begin
//暫停若干秒
Sleep(Config.Delaytime);
//發(fā)送
ExportData.Comm1.WriteCommData(@CurrChar, 1);
end;
//當(dāng)前位置增量
Inc(Pos);
//線程調(diào)用函數(shù)輸出進(jìn)度信息
Synchronize(Percent);
end;
//如果發(fā)送完了
if Pos = Len + 1 then
begin
CurrChar := Chr($17);
Sleep(100);
//輸出結(jié)束標(biāo)志17H,參看通訊協(xié)議
ExportData.Comm1.WriteCommData(@CurrChar, 1);
Synchronize(ok);
end;
// Self.Terminate;
// PostMessage(Application.Handle, WM_QUIT, 0, 0); ;
end;
procedure TSendThread.Ok;
begin
ExportData.pgb1.Percent := 100;
ExportData.Lbl4.Font.Style := [fsbold];
ExportData.Lbl5.Visible := True;
ExportData.Lbl5.Caption := '花費(fèi)時(shí)間:' + IntToStr(GetTickCount -
ExportData.TickCount) +
'毫秒';
ExportData.btnFinish.Caption := '完成';
ExportData.bstart := False;
end;
procedure TSendThread.Percent;
begin
ExportData.pgb1.Percent := trunc((Pos / Len) * 100);
end;
procedure TExportData.FormShow(Sender: TObject);
begin
//顯示窗體時(shí)初始化
pgcMain.ActivePageIndex := 0;
btnPrior.Enabled := False;
btnNext.Enabled := True;
btnFinish.Caption := '取消';
Comm1.StopComm;
SendText.Clear;
end;
constructor TExportData.Create(const id: Integer);
begin
inherited Create(Application);
Fid := id;
end;
end.
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -