CnModem.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnModem;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:网络通讯组件包
  24. * 单元名称:CnModem标准调制解调器组件单元
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 备 注:CnModem组件由CnRS232串口通讯组件派生而来
  27. * 提供利用AT命令通过串口直接操作调制解调器的功能
  28. * 开发平台:PWin98SE + Delphi 5.0
  29. * 兼容测试:PWin9X/2000/XP + Delphi 5/6
  30. * 本 地 化:该单元中的字符串均符合本地化处理方式
  31. * 单元标识:$Id$
  32. * 修改记录:2002.04.08 V1.0
  33. * 创建单元
  34. * 增加注释
  35. ================================================================================
  36. |</PRE>}
  37. interface
  38. {$I CnPack.inc}
  39. uses
  40. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  41. CnConsts, CnNetConsts, CnRS232, IniFiles;
  42. type
  43. //------------------------------------------------------------------------------
  44. // 标准调制解调器组件
  45. //------------------------------------------------------------------------------
  46. { TCnModem }
  47. TDialResult = (drConnect, drOpenCommFail, drNoModem, drNoDialtone, drBusy,
  48. drNoAnswer, drNoCarrier, drTimeout, drUnknow);
  49. {* Modem拨号结果类型
  50. |<PRE>
  51. drConnect: - 连接成功
  52. drOpenCommFail: - 打开串口失败
  53. drNoModem: - 没有检测到Modem
  54. drNoDialtone: - 无拨号音
  55. drBusy: - 检测到忙信号
  56. drNoAnswer: - 无应答信号
  57. drNoCarrier: - 没有检测到载波信号
  58. drTimeout: - 超时错
  59. drUnknow: - 未知错误
  60. |</PRE>}
  61. TATResult = (arOk, arConnect, arRing, arNoCarrier, arError, arNoDialtone,
  62. arBusy, arNoAnswer, arTimeout, arUnknow);
  63. {* AT命令执行结果类型
  64. |<PRE>
  65. arOk: - 成功
  66. arConnect: - 已连接
  67. arRing: - 振铃信号
  68. arNoCarrier: - 没有检测到载波信号
  69. arError: - 执行错误
  70. arNoDialtone: - 无拨号音
  71. arBusy: - 检测到忙信号
  72. arNoAnswer: - 无应答信号
  73. arTimeout: - 超时错
  74. arUnknow: - 未知错误
  75. |</PRE>}
  76. TModemVolume = (mvLowest, mvLow, mvMiddle, mvHigh);
  77. {* Modem 音量
  78. |<PRE>
  79. mvLowest: - 最小音量
  80. mvLow: - 小音量
  81. mvMiddle: - 中等音量
  82. mvHigh: - 大音量
  83. |</PRE>}
  84. TRingEvent = procedure(Sender: TObject; var Answer: Boolean) of object;
  85. {* 接收到振铃事件,变量参数Answer决定是否应答}
  86. TConnectEvent = procedure(Sender: TObject; Rate: Integer) of object;
  87. {* 已连接成功事件,参数Rate为连接速度}
  88. TInvalidCommandEvent = procedure(Sender: TObject; const Command: string) of object;
  89. {* 非法的AT命令事件,参数为出错的命令行}
  90. TModemState = (msUnknow, msOffline, msOnline, msOnlineCommand, msConnecting);
  91. {* 当前Modem状态类型
  92. |<PRE>
  93. msUnknow: - 未知状态
  94. msOffline: - 离线状态
  95. msOnline: - 在线状态
  96. msOnlineCommand: - 在线命令状态
  97. msConnecting: - 正在连接状态
  98. |</PRE>}
  99. TStateChangeEvent = procedure(Sender: TObject; State: TModemState) of object;
  100. {* 当前Modem状态改变事件}
  101. TCnModem = class(TCnRS232)
  102. {* 标准调制解调器通讯组件
  103. |<PRE>
  104. * 组件由TCnRS232派生而来,通过向串口发送AT命令来控制标准 Modem 通讯。
  105. * 使用时可直接调用 Dial 方法进行拨号连接,拨号完成返回执行结果。
  106. * 当 Modem 检测到振铃信号时,产生 OnRing 事件。
  107. * Hangup 方法可挂机拆除连接,通讯时如果连接中断,将产生 OnDisConnect 事件。
  108. * 连接成功后通过使用继承来的方法 WriteCommData 向 Modem 发送数据。
  109. * 只有当 Modem 处于在线状态时,收到数据才会产生 OnReceiveData 事件。
  110. |</PRE>}
  111. private
  112. { Private declarations }
  113. FCheckDialtone: Boolean;
  114. FCheckBusy: Boolean;
  115. FAutoAnswer: Boolean;
  116. FVolume: TModemVolume;
  117. FWaitEscapeTime: Integer;
  118. FWaitDialtoneTime: Integer;
  119. FWaitCarrierTime: Integer;
  120. FInitATCommand: string;
  121. FModemState: TModemState;
  122. FOnConnect: TConnectEvent;
  123. FOnDisConnect: TNotifyEvent;
  124. FOnRing: TRingEvent;
  125. FOnInvalidCommand: TInvalidCommandEvent;
  126. FOnStateChange: TStateChangeEvent;
  127. FWaitATResult: Boolean;
  128. FATResult: string;
  129. FConnectRate: Integer;
  130. procedure SetAutoAnswer(const Value: Boolean);
  131. procedure SetVolume(const Value: TModemVolume);
  132. procedure SetInitATCommand(const Value: string);
  133. procedure SetWaitCarrierTime(const Value: Integer);
  134. procedure SetWaitDialtoneTime(const Value: Integer);
  135. procedure SetWaitEscapeTime(const Value: Integer);
  136. procedure SetCheckBusy(const Value: Boolean);
  137. procedure SetCheckDialtone(const Value: Boolean);
  138. procedure SetModemState(const Value: TModemState);
  139. function WaitATResult(Delay: Cardinal): string;
  140. function SendATOk(AT: string; Delay: Cardinal = 200): Boolean;
  141. function StrToIntEx(const Str: string): Integer;
  142. protected
  143. { Protected declarations }
  144. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  145. function CommOpened: Boolean;
  146. function OpenComm: Boolean;
  147. procedure Changed;
  148. procedure ReceiveData(Buffer: PAnsiChar; BufferLength: WORD); override;
  149. procedure _SendDataEmpty; override;
  150. procedure Ring; virtual;
  151. procedure Connect(Rate: Integer); virtual;
  152. procedure DisConnect; virtual;
  153. procedure InvalidCommand(const Command: string); virtual;
  154. procedure Escape;
  155. procedure Resume;
  156. function Answer: TDialResult;
  157. property ModemState: TModemState read FModemState write SetModemState;
  158. public
  159. { Public declarations }
  160. procedure Assign(Source: TPersistent); override;
  161. {* 对象赋值方式}
  162. constructor Create(AOwner: TComponent); override;
  163. destructor Destroy; override;
  164. function InitModem: Boolean;
  165. {* 初始化Modem,一般不需要手工调用}
  166. function Dial(const Number: string): TDialResult;
  167. {* 拨号方法,参数为对方电话机号码}
  168. procedure WriteATCommand(const Command: string; Return: Boolean = True);
  169. {* 写AT命令方法,允许用户手工向 Modem 发送AT命令。
  170. |<PRE>
  171. Command: string - AT命令行
  172. Return: Boolean - 是否自动在命令行末尾增加回车,默认为是
  173. |</PRE>}
  174. procedure Hangup;
  175. {* 挂机拆除当前连接}
  176. procedure ReadFromIni(Ini: TCustomIniFile; const Section: string); override;
  177. procedure WriteToIni(Ini: TCustomIniFile; const Section: string); override;
  178. property State: TModemState read FModemState;
  179. {* 当前的 Modem 状态,运行期只读属性}
  180. property ConnectRate: Integer read FConnectRate;
  181. {* 当前的连接速度,运行期只读属性}
  182. published
  183. { Published declarations }
  184. property CheckDialtone: Boolean read FCheckDialtone write SetCheckDialtone default
  185. True;
  186. {* 拨号前是否检测拨号音}
  187. property CheckBusy: Boolean read FCheckBusy write SetCheckBusy default True;
  188. {* 拨号前是否检测忙信号}
  189. property AutoAnswer: Boolean read FAutoAnswer write SetAutoAnswer default False;
  190. {* 是否允许自动应答。如果允许,不管在 OnRing 事件是否允许,都将自动应答}
  191. property Volume: TModemVolume read FVolume write SetVolume default mvMiddle;
  192. {* Modem 音量}
  193. property WaitDialtoneTime: Integer read FWaitDialtoneTime write SetWaitDialtoneTime
  194. default 2;
  195. {* 等待拨号音的最长时间,单位为秒}
  196. property WaitCarrierTime: Integer read FWaitCarrierTime write SetWaitCarrierTime
  197. default 50;
  198. {* 等待检测载波的最长时间,单位为秒}
  199. property WaitEscapeTime: Integer read FWaitEscapeTime write SetWaitEscapeTime
  200. default 50;
  201. {* 切换到在线命令状态的等待时间,单位为 20 毫秒}
  202. property InitATCommand: string read FInitATCommand write SetInitATCommand;
  203. {* 用于初始化 Modem 的额外AT命令,仅建议高级用户使用}
  204. property OnRing: TRingEvent read FOnRing write FOnRing;
  205. {* 振铃事件}
  206. property OnConnect: TConnectEvent read FOnConnect write FOnConnect;
  207. {* 连接成功事件}
  208. property OnInvalidCommand: TInvalidCommandEvent read FOnInvalidCommand write
  209. FOnInvalidCommand;
  210. {* 检测到无效的AT命令事件}
  211. property OnDisConnect: TNotifyEvent read FOnDisConnect write FOnDisConnect;
  212. {* 连接中断事件}
  213. property OnStateChange: TStateChangeEvent read FOnStateChange write FOnStateChange;
  214. {* Modem 状态改变事件}
  215. end;
  216. implementation
  217. //------------------------------------------------------------------------------
  218. // 标准调制解调器组件
  219. //------------------------------------------------------------------------------
  220. { TCnModem }
  221. // 对象赋值方法
  222. procedure TCnModem.Assign(Source: TPersistent);
  223. begin
  224. if Source is TCnModem then
  225. begin
  226. FCheckDialtone := TCnModem(Source).FCheckDialtone;
  227. FCheckBusy := TCnModem(Source).FCheckBusy;
  228. FAutoAnswer := TCnModem(Source).FAutoAnswer;
  229. FWaitEscapeTime := TCnModem(Source).FWaitEscapeTime;
  230. FWaitDialtoneTime := TCnModem(Source).FWaitDialtoneTime;
  231. FWaitCarrierTime := TCnModem(Source).FWaitCarrierTime;
  232. FInitATCommand := TCnModem(Source).FInitATCommand;
  233. end;
  234. inherited;
  235. end;
  236. // 初始化
  237. constructor TCnModem.Create(AOwner: TComponent);
  238. begin
  239. inherited;
  240. FCheckDialtone := True;
  241. FCheckBusy := True;
  242. FAutoAnswer := False;
  243. FVolume := mvMiddle;
  244. FWaitDialtoneTime := 2;
  245. FWaitCarrierTime := 50;
  246. FWaitEscapeTime := 50;
  247. FInitATCommand := '';
  248. FModemState := msOffline;
  249. FWaitATResult := False;
  250. FATResult := '';
  251. FConnectRate := 0;
  252. CommConfig.Outx_CtsFlow := True;
  253. CommConfig.Outx_DsrFlow := True;
  254. end;
  255. // 释放
  256. destructor TCnModem.Destroy;
  257. begin
  258. Hangup;
  259. inherited;
  260. end;
  261. // 通讯状态
  262. function TCnModem.CommOpened: Boolean;
  263. begin
  264. Result := Handle <> 0;
  265. end;
  266. // 打开串口,返回成功标记
  267. function TCnModem.OpenComm: Boolean;
  268. begin
  269. Result := CommOpened;
  270. if not Result then
  271. begin
  272. try
  273. StartComm;
  274. Result := True;
  275. except
  276. Exit;
  277. end;
  278. end;
  279. end;
  280. // 属性已变更
  281. procedure TCnModem.Changed;
  282. begin
  283. if (ComponentState * [csDesigning, csLoading, csDestroying] = [])
  284. and CommOpened then
  285. InitModem;
  286. end;
  287. // 发送数据缓冲区空
  288. procedure TCnModem._SendDataEmpty;
  289. begin
  290. if ModemState = msOnline then // 仅在离线状态下产生事件
  291. inherited;
  292. end;
  293. // 字符串转换为整数
  294. function TCnModem.StrToIntEx(const Str: string): Integer;
  295. var
  296. SInt: string;
  297. i: Integer;
  298. begin
  299. SInt := '';
  300. for i := 1 to Length(Str) do
  301. if {$IFDEF UNICODE}CharInSet(Str[i], ['0'..'9']){$ELSE}Str[i] in ['0'..'9']{$ENDIF} then // 仅取数字字符
  302. SInt := SInt + Str[i];
  303. if SInt <> '' then
  304. Result := StrToInt(SInt)
  305. else
  306. Result := 0;
  307. end;
  308. // 发送AT命令到串口
  309. procedure TCnModem.WriteATCommand(const Command: string; Return: Boolean);
  310. var
  311. s: AnsiString;
  312. begin
  313. if (csDesigning in ComponentState) or not CommOpened then
  314. Exit;
  315. if Return then
  316. s := {$IFDEF UNICODE}AnsiString{$ENDIF}(Command) + #13
  317. else
  318. s := {$IFDEF UNICODE}AnsiString{$ENDIF}(Command);
  319. WriteCommData(PAnsiChar(s), Length(s));
  320. end;
  321. // 等待一条AT命令执行结果
  322. function TCnModem.WaitATResult(Delay: Cardinal): string;
  323. var
  324. Tick: Cardinal;
  325. begin
  326. FWaitATResult := True;
  327. try
  328. FATResult := '';
  329. Tick := GetTickCount;
  330. while (GetTickCount - Tick < Delay) and (FATResult = '') do
  331. Application.HandleMessage;
  332. Result := FATResult;
  333. FATResult := '';
  334. finally
  335. FWaitATResult := False;
  336. end;
  337. end;
  338. // 发送一条AT命令,返回是否成功
  339. function TCnModem.SendATOk(AT: string; Delay: Cardinal): Boolean;
  340. var
  341. i, j: Integer;
  342. s: string;
  343. begin
  344. Result := False;
  345. for i := 0 to 2 do
  346. begin
  347. WriteATCommand(AT);
  348. for j := 0 to 2 do
  349. begin
  350. s := Trim(UpperCase(WaitATResult(Delay)));
  351. if Pos('OK', s) > 0 then
  352. begin
  353. Result := True;
  354. Exit;
  355. end
  356. else if Pos('ERROR', s) > 0 then
  357. begin
  358. InvalidCommand(AT);
  359. Exit;
  360. end;
  361. end;
  362. end;
  363. end;
  364. // 接收到数据
  365. procedure TCnModem.ReceiveData(Buffer: PAnsiChar; BufferLength: WORD);
  366. var
  367. s: AnsiString;
  368. begin
  369. if FWaitATResult then // 正在等待AT命令执行结果
  370. begin
  371. FATResult := {$IFDEF UNICODE}String{$ENDIF}(Buffer);
  372. Exit;
  373. end;
  374. s := Buffer;
  375. s := {$IFDEF UNICODE}AnsiString{$ENDIF}(Trim(UpperCase({$IFDEF UNICODE}String{$ENDIF}(s))));
  376. if (ModemState in [msOffline, msOnlineCommand, msConnecting]) and (s = 'RING') then
  377. Ring // 振铃信号
  378. else if (ModemState = msOnline) and (s = 'NO CARRIER') then
  379. DisConnect // 载波丢失
  380. else
  381. inherited;
  382. end;
  383. // 拨号
  384. function TCnModem.Dial(const Number: string): TDialResult;
  385. var
  386. s: string;
  387. begin
  388. if not OpenComm then
  389. begin
  390. Result := drOpenCommFail;
  391. Exit;
  392. end;
  393. Result := drNoModem;
  394. if InitModem then
  395. begin
  396. WriteATCommand('ATD' + Number);
  397. ModemState := msConnecting;
  398. s := Trim(UpperCase(WaitATResult(Round(WaitCarrierTime * 1000 * 1.2))));
  399. if Pos('CONNECT', s) > 0 then
  400. begin
  401. Result := drConnect;
  402. FConnectRate := StrToIntEx(s);
  403. ModemState := msOnline;
  404. Exit;
  405. end;
  406. if Pos('NO DIALTONE', s) > 0 then
  407. Result := drNoDialtone
  408. else if Pos('BUSY', s) > 0 then
  409. Result := drBusy
  410. else if Pos('NO CARRIER', s) > 0 then
  411. Result := drNoCarrier
  412. else if Pos('NO ANSWER', s) > 0 then
  413. Result := drNoAnswer
  414. else if s = '' then
  415. Result := drTimeout
  416. else
  417. Result := drUnknow;
  418. ModemState := msOffline;
  419. end;
  420. end;
  421. // 应答
  422. function TCnModem.Answer: TDialResult;
  423. var
  424. s: string;
  425. begin
  426. Result := drUnknow;
  427. if CommOpened and (ModemState = msOffline) then
  428. begin
  429. WriteATCommand('ATA');
  430. ModemState := msConnecting;
  431. s := Trim(UpperCase(WaitATResult(Round(WaitCarrierTime * 1000 * 1.2))));
  432. if Pos('CONNECT', s) > 0 then
  433. begin
  434. FConnectRate := StrToIntEx(s);
  435. ModemState := msOnline;
  436. Connect(FConnectRate);
  437. Result := drConnect;
  438. Exit;
  439. end;
  440. if Pos('NO DIALTONE', s) > 0 then
  441. Result := drNoDialtone
  442. else if Pos('BUSY', s) > 0 then
  443. Result := drBusy
  444. else if Pos('NO CARRIER', s) > 0 then
  445. Result := drNoCarrier
  446. else if Pos('NO ANSWER', s) > 0 then
  447. Result := drNoAnswer
  448. else if s = '' then
  449. Result := drTimeout
  450. else
  451. Result := drUnknow;
  452. ModemState := msOffline;
  453. end;
  454. end;
  455. // 切换到在线命令状态
  456. procedure TCnModem.Escape;
  457. var
  458. Tick: Integer;
  459. begin
  460. if CommOpened and (ModemState = msOnline) then
  461. begin
  462. Tick := Round(FWaitEscapeTime * 20 * 1.3);
  463. Sleep(Tick);
  464. WriteATCommand('+++', False);
  465. Sleep(Tick);
  466. ModemState := msOnlineCommand;
  467. end;
  468. end;
  469. // 回到在线状态
  470. procedure TCnModem.Resume;
  471. begin
  472. if CommOpened and (ModemState = msOnlineCommand) then
  473. begin
  474. if SendATOk('ATO') then
  475. ModemState := msOnline
  476. else
  477. Hangup;
  478. end;
  479. end;
  480. // 挂机
  481. procedure TCnModem.Hangup;
  482. begin
  483. if CommOpened then
  484. begin
  485. Escape;
  486. WriteATCommand('ATH');
  487. Sleep(1000);
  488. ModemState := msOffline;
  489. StopComm;
  490. end;
  491. end;
  492. // 初始化 Modem
  493. function TCnModem.InitModem: Boolean;
  494. const
  495. AutoAnswers: array[Boolean] of Integer = (0, 1);
  496. Checks: array[Boolean, Boolean] of Integer = ((0, 2), (3, 4));
  497. begin
  498. Result := False;
  499. if not OpenComm then
  500. Exit;
  501. if ModemState <> msOffline then
  502. Hangup;
  503. if not SendATOk('ATQ0E0V1') then Exit; //命令不回显,以字符形式显示结果码
  504. if not SendATOk('ATX' + IntToStr(Checks[CheckDialtone, CheckBusy])) then Exit;
  505. if not SendATOk('ATL' + IntToStr(Ord(FVolume))) then Exit;
  506. if not SendATOk('ATS0=' + IntToStr(AutoAnswers[AutoAnswer])) then Exit;
  507. if not SendATOk('ATS6=' + IntToStr(WaitDialtoneTime)) then Exit;
  508. if not SendATOk('ATS7=' + IntToStr(WaitCarrierTime)) then Exit;
  509. if not SendATOk('ATS12=' + IntToStr(WaitEscapeTime)) then Exit;
  510. Result := True;
  511. if InitATCommand <> '' then
  512. SendATOk(InitATCommand);
  513. end;
  514. // 非法AT命令
  515. procedure TCnModem.InvalidCommand(const Command: string);
  516. begin
  517. if Assigned(FOnInvalidCommand) then
  518. FOnInvalidCommand(Self, Command);
  519. end;
  520. // 已连接
  521. procedure TCnModem.Connect(Rate: Integer);
  522. begin
  523. if Assigned(FOnConnect) then
  524. FOnConnect(Self, Rate);
  525. end;
  526. // 连接中断
  527. procedure TCnModem.DisConnect;
  528. begin
  529. if Assigned(FOnDisConnect) then
  530. FOnDisConnect(Self);
  531. end;
  532. // 振铃事件
  533. procedure TCnModem.Ring;
  534. var
  535. Ans: Boolean;
  536. begin
  537. Ans := True;
  538. if Assigned(FOnRing) then
  539. FOnRing(Self, Ans);
  540. if not AutoAnswer and Ans then
  541. Answer;
  542. end;
  543. // 设置Modem状态
  544. procedure TCnModem.SetModemState(const Value: TModemState);
  545. begin
  546. if FModemState <> Value then
  547. begin
  548. FModemState := Value;
  549. if Assigned(FOnStateChange) then
  550. FOnStateChange(Self, FModemState);
  551. end;
  552. end;
  553. // 设置自动应答
  554. procedure TCnModem.SetAutoAnswer(const Value: Boolean);
  555. begin
  556. if FAutoAnswer <> Value then
  557. begin
  558. FAutoAnswer := Value;
  559. Changed;
  560. end;
  561. end;
  562. // 设置音量
  563. procedure TCnModem.SetVolume(const Value: TModemVolume);
  564. begin
  565. if FVolume <> Value then
  566. begin
  567. FVolume := Value;
  568. Changed;
  569. end;
  570. end;
  571. // 设置初始化AT命令
  572. procedure TCnModem.SetInitATCommand(const Value: string);
  573. begin
  574. if FInitATCommand <> Value then
  575. begin
  576. FInitATCommand := UpperCase(Trim(Value));
  577. if Pos('AT', FInitATCommand) <> 1 then
  578. FInitATCommand := 'AT' + FInitATCommand;
  579. if FInitATCommand = 'AT' then
  580. FInitATCommand := '';
  581. Changed;
  582. end;
  583. end;
  584. // 设置等待载波时间
  585. procedure TCnModem.SetWaitCarrierTime(const Value: Integer);
  586. begin
  587. if FWaitCarrierTime <> Value then
  588. begin
  589. FWaitCarrierTime := Value;
  590. Changed;
  591. end;
  592. end;
  593. // 设置等待拨号音时间
  594. procedure TCnModem.SetWaitDialtoneTime(const Value: Integer);
  595. begin
  596. if FWaitDialtoneTime <> Value then
  597. begin
  598. FWaitDialtoneTime := Value;
  599. Changed;
  600. end;
  601. end;
  602. // 设置切换到在线命令状态的等待时间
  603. procedure TCnModem.SetWaitEscapeTime(const Value: Integer);
  604. begin
  605. if FWaitEscapeTime <> Value then
  606. begin
  607. FWaitEscapeTime := Value;
  608. Changed;
  609. end;
  610. end;
  611. // 设置检测忙音
  612. procedure TCnModem.SetCheckBusy(const Value: Boolean);
  613. begin
  614. if FCheckBusy <> Value then
  615. begin
  616. FCheckBusy := Value;
  617. Changed;
  618. end;
  619. end;
  620. // 设置检测拨号音
  621. procedure TCnModem.SetCheckDialtone(const Value: Boolean);
  622. begin
  623. if FCheckDialtone <> Value then
  624. begin
  625. FCheckDialtone := Value;
  626. Changed;
  627. end;
  628. end;
  629. const
  630. csCheckDialtone = 'CheckDialtone';
  631. csCheckBusy = 'CheckBusy';
  632. csAutoAnswer = 'AutoAnswer';
  633. csWaitEscapeTime = 'WaitEscapeTime';
  634. csWaitDialtoneTime = 'WaitDialtoneTime';
  635. csWaitCarrierTime = 'WaitCarrierTime';
  636. csInitATCommand = 'InitATCommand';
  637. // 从INI中读参数
  638. procedure TCnModem.ReadFromIni(Ini: TCustomIniFile;
  639. const Section: string);
  640. begin
  641. inherited;
  642. FCheckDialtone := Ini.ReadBool(Section, csCheckDialtone, FCheckDialtone);
  643. FCheckBusy := Ini.ReadBool(Section, csCheckBusy, FCheckBusy);
  644. FAutoAnswer := Ini.ReadBool(Section, csAutoAnswer, FAutoAnswer);
  645. FWaitEscapeTime := Ini.ReadInteger(Section, csWaitEscapeTime, FWaitEscapeTime);
  646. FWaitDialtoneTime := Ini.ReadInteger(Section, csWaitDialtoneTime, FWaitDialtoneTime);
  647. FWaitCarrierTime := Ini.ReadInteger(Section, csWaitCarrierTime, FWaitCarrierTime);
  648. FInitATCommand := Ini.ReadString(Section, csInitATCommand, FInitATCommand);
  649. FInitATCommand := UpperCase(Trim(FInitATCommand));
  650. if Pos('AT', FInitATCommand) <> 1 then
  651. FInitATCommand := 'AT' + FInitATCommand;
  652. if FInitATCommand = 'AT' then
  653. FInitATCommand := '';
  654. end;
  655. // 写参数到INI
  656. procedure TCnModem.WriteToIni(Ini: TCustomIniFile; const Section: string);
  657. begin
  658. inherited;
  659. Ini.WriteBool(Section, csCheckDialtone, FCheckDialtone);
  660. Ini.WriteBool(Section, csCheckBusy, FCheckBusy);
  661. Ini.WriteBool(Section, csAutoAnswer, FAutoAnswer);
  662. Ini.WriteInteger(Section, csWaitEscapeTime, FWaitEscapeTime);
  663. Ini.WriteInteger(Section, csWaitDialtoneTime, FWaitDialtoneTime);
  664. Ini.WriteInteger(Section, csWaitCarrierTime, FWaitCarrierTime);
  665. Ini.WriteString(Section, csInitATCommand, FInitATCommand);
  666. end;
  667. // 取组件注释
  668. procedure TCnModem.GetComponentInfo(var AName, Author, Email, Comment: string);
  669. begin
  670. AName := SCnModemName;
  671. Author := SCnPack_Zjy;
  672. Email := SCnPack_ZjyEmail;
  673. Comment := SCnModemComment;
  674. end;
  675. end.