PB串口编程资料

原文地址:PB串口编程资料几则(转)    原文作者:notbig

PB串口编程资料
----MSCOMM32参数基本介绍
MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法。具体的来说,它提供了两种处理通信问题的方法:一是事件驱动(Event-driven)方法,一是查询法。
1.MSComm控件两种处理通讯的方式
MSComm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。 
1.1 事件驱动方式
事件驱动通讯是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 线上一个字符到达或一个变化发生时。在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件。OnComm 事件还可以检查和处理通讯错误。所有通讯事件和通讯错误的列表,参阅 CommEvent 属性。在编程过程中,就可以在OnComm事件处理函数中加入自己的处理代码。这种方法的优点是程序响应及时,可靠性高。每个MSComm 控件对应着一个串行端口。如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件。
1.2 查询方式
查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷。在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误。如果应用程序较小,并且是自保持的,这种方法可能是更可取的。例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“确定”响应。
2.MSComm 控件的常用属性
MSComm 控件有很多重要的属性,但首先必须熟悉几个属性。
CommPort 设置并返回通讯端口号。 
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。 
PortOpen 设置并返回通讯端口的状态。也可以打开和关闭端口。 
Input 从接收缓冲区返回和删除字符。 
Output 向传输缓冲区写一个字符串。
下面分别描述:
CommPort属性 设置并返回通讯端口号。
语法: object.CommPort[value ] (value 一整型值,说明端口号。) 
说明:在设计时,value 可以设置成从 1 到 16 的任何数(缺省值为 1)。但是如果用 PortOpen 属性打开一个并不存在的端口时,MSComm 控件会产生错误 68(设备无效)。
注意:必须在打开端口之前设置 CommPort 属性。
RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生 OnComm 之前,设置并返回的要接收的字符数。
语法 object.Rthreshold [ = value ](value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数。 )
说明 当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件。例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件。
CTSHolding 属性:确定是否可通过查询 Clear To Send (CTS) 线的状态发送数据。Clear To Send 是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。
语法: object.CTSHolding(Boolean)
Mscomm 控件的 CTSHolding 属性设置值:
True      Clear To Send 线为高电平。 
False     Clear To Send 线为低电平。
说明:如果 Clear To Send 线为低电平 (CTSHolding = False) 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO (Clear To Send Timeout) 并产生 OnComm 事件。
Clear To Send 线用于 RTS/CTS (Request To Send/Clear To Send) 硬件握手。如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法。
详细信息 有关握手协议,请参阅 Handshaking 属性。
SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm 事件之前,设置并返回传输缓冲区中允许的最小字符数。
语法 object.SThreshold [ = value ]
value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数。
说明:若设置 Sthreshold 属性为 0(缺省值),数据传输事件不会产生 OnComm 事件。若设置 Sthreshold 属性为 1,当传输缓冲区完全空时,MSComm 控件产生 OnComm 事件。如果在传输缓冲区中的字符数小于 value,CommEvent 属性设置为 comEvSend,并产生 OnComm 事件。comEvSend 事件仅当字符数与 Sthreshold 交叉时被激活一次。例如,如果 Sthreshold 等于 5,仅当在输出队列中字符数从 5 降到 4 时,comEvSend 才发生。如果在输出队列中从没有比 Sthreshold 多的字符,comEvSend 事件将绝不会发生。
Handshake 常数
常数          值          描述 
comNone       0           无握手。 
comXonXoff    1           XOn/Xoff 握手。 
comRTS        2           Request-to-send/clear-to-send 握手。 
comRTSXOnXOff 3           Request-to-send 和 clear-to-send 握手皆可。
OnComm 常数
常数          值       描述 
comEvSend     1        发送事件。 
comEvReceive 2        接收事件。 
comEvCTS      3        clear-to-send 线变化。 
comEvDSR      4        data-set ready 线变化。 
comEvCD       5        carrier detect 线变化。 
comEvRing     6        振铃检测。 
comEvEOF      7        文件结束。
Error 常数
常数             值        描述 
comEventBreak    1001   接收到中断信号 
comEventCTSTO    1002   Clear-to-send 超时 
comEventDSRTO    1003   Data-set ready 超时 
comEventFrame    1004   帧错误 
comEventOverrun 1006   端口超速 
comEventCDTO     1007   Carrier detect 超时 
comEventRxOver   1008   接收缓冲区溢出 
comEventRxParity 1009   Parity 错误 
comEventTxFull   1010   传输缓冲区满 
comEventDCB      1011   检索端口 设备控制块 (DCB) 时的意外错误
InputMode 常数
常数               值    描述 
comInputModeText   0    (缺省)通过 Input 属性以文本方式取回数据。 
comInputModeBinary 1     通过 Input 属性以二进制方式检取回数据。
CDHolding 属性:通过查询 Carrier Detect (CD) 线的状态确定当前是否有传输。Carrier Detect 是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。
语法 object.CDHolding
设置值:CDHolding 属性的设置值为:
设置    描述 
True    Carrier Detect 线为高电平 
False   Carrier Detect 线为低电平 
说明:注意当 Carrier Detect 线为高电平 (CDHolding = True) 且超时时,MSComm 控件设置CommEvent 属性为 comEventCDTO(Carrier Detect 超时错误),并产生 OnComm 事件。
注意: 在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输)。
Carrier Detect 也被称为 Receive Line Signal Detect (RLSD)。
数据类型 Boolean
DSRHolding 属性:确定 Data Set Ready (DSR) 线的状态。Data Set Ready 信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。
语法:object.DSRHolding
object 所在处表示对象表达式,其值是“应用于”列表中的对象。
DSRHolding 属性返回以下值:
值     描述 
True   Data Set Ready 线高 
False Data Set Ready 线低 
说明:当 Data Set Ready 线为高电平 (DSRHolding = True) 且超时时,MSComm 控件设置 CommEvent 属性为 comEventDSRTO(数据准备超时)并产生 OnComm 事件。当为 Data Terminal Equipment (DTE) 机器写 Data Set Ready/Data Terminal Ready 握手例程时该属性是十分有用的。
数据类型:Boolean
Settings 属性: 设置并返回波特率、奇偶校验、数据位、停止位参数。
语法: object.Settings[ = value]
说明:当端口打开时,如果 value 非法,则 MSComm 控件产生错误 380(非法属性值)。
Value 由四个设置值组成,有如下的格式:
"BBBB,P,D,S"
BBBB 为波特率,P 为奇偶校验,D 为数据位数,S 为停止位数。
value 的缺省值是:"9600,N,8,1"
InputLen 属性:设置并返回 Input 属性从接收缓冲区读取的字符数。
语法 object.InputLen [ = value]
InputLen 属性语法包括下列部分:
value 整型表达式,说明 Input 属性从接收缓冲区中读取的字符数。 
说明:InputLen 属性的缺省值是 0。设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。
若接收缓冲区中 InputLen 字符无效,Input 属性返回一个零长度字符串 ("")。在使用 Input 前,用户可以选择检查 InBufferCount 属性来确定缓冲区中是否已有需要数目的字符。该属性在从输出格式为定长数据的机器读取数据时非常有用。
EOFEnable 属性:确定在输入过程中 MSComm 控件是否寻找文件结尾 (EOF) 字符。如果找到 EOF 字符,将停止输入并激活 OnComm 事件,此时 CommEvent 属性设置为 comEvEOF,
语法:object.EOFEnable [ = value ]
EOFEnable 属性语法包括下列部分:
value 布尔表达式,确定当找到 EOF 字符时,OnComm 事件是否被激活,如“设置值”中所描述。 
value 的设置值:
True 当 EOF 字符找到时 OnComm 事件被激活。 
False (缺省)当 EOF 字符找到时 OnComm 事件不被激活。 
说明:当 EOFEnable 属性设置为 False,OnComm 控件将不在输入流中寻找 EOF 字符。
错误消息(MS Comm 控件)
下表列出 MSComm 控件可以捕获的错误:
值    描述 
380   无效属性值 comInvalidPropertyValue
383   属性为只读 comSetNotSupported
394   属性为只读 comGetNotSupported 
8000 端口打开时操作不合法 comPortOpen
8001 超时值必须大于 0 
8002 无效端口号 comPortInvalid
8003 属性只在运行时有效 
8004 属性在运行时为只读 
8005 端口已经打开 comPortAlreadyOpen
8006 设备标识符无效或不支持该标识符 
8007 不支持设备的波特率 
8008 指定的字节大小无效 
8009 缺省参数错误 
8010 硬件不可用(被其它设备锁定) 
8011 函数不能分配队列 
8012 设备没有打开 comNoOpen 
8013 设备已经打开 
8014 不能使用 comm 通知 
8015 不能设置 comm 状态 comSetCommStateFailed
8016 不能设置 comm 事件屏蔽 
8018 仅当端口打开时操作才有效 comPortNotOpen 
8019 设备忙 
8020 读 comm 设备错误 comReadError
8021 为该端口检索设备控制块时的内部错误 comDCBError

PowerBuilder中串行通信编程技术研究

 摘要:介绍了在PowerBuilder 中调用Win32 API函数、使用Mscomm32.ocx通信控件、利用VCL通信组件和调用DLL(动态链接库)中的函数来实现串行通信的方法,分析总结了各种方法的优缺点。 

  关键词:串行通信;事件驱动;应用程序接口;动态链接库 

  0 引言 

  在自动控制中,用PC机对工程实现实时监控,通常要求PC机能在用户界面上具有数据采集、数据处理以及控制信号的产生与传输等功能。在这种情况下,PC机要与过程控制的信号相联系,就要求能实现对PC机的串行端口直接操作。串行通信具有传输距离长、连接简单、使用灵活方便、数据传输可靠性高等特点,在工业监控、数据采集和实时控制系统中得到了广泛应用。 

  PowerBuilder(简称PB)是一种可视化的、面向对象的快速交互式应用开发工具。PB以其简洁高效的集成开发环境、强大的数据窗口技术、便捷的报表生成及打印功能,越来越受到广大开发人员的青睐。在各种开发软件中,PB对于数据库的上层编程支持是名列前茅的,但是,PB对计算机的底层支持略显薄弱,没有提供串行通信的命令、函数或控件,与其它设备之间进行数据通信较为困难,笔者根据自己在PB编程中积累的经验,介绍了几种在PB中实现串行通信的方法。 

  1 串行数据通信 

  1.1 工作原理 

  Windows是一个事件驱动的与设备无关的多用户操作系统,它禁止应用程序直接和硬件交互,程序员只能通过Windows提供的各类驱动程序来管理硬件。Windows系统函数包含了通信支持中断功能,Windows系统为每个通信设备开辟了用户定义的输入输出缓冲区(即读写缓冲区),数据进出通信口均由系统后台来完成。应用程序只需完成对输入输出缓冲区操作就可以了。实际过程是每接收一个数据就产生一个低级硬件中断,Windows系统中的串行驱动程序就取得了控制权,并将接收到的数据放入输入数据缓冲区,然后将控制权返还正在运行的应用程序。如果缓冲区数据已满,串行驱动程序用当前定义的流控制机制通知发送方停止发送数据。队列中的数据按“先进先出”的次序处理。 

  1.2 通信方式 

  串行通信的数据是一位接一位顺序地传送下去,通信方式有以下几种: 

  (1)异步通信方式 

  异步通信方式中,数据是一帧一帧(包括一个字符或一字节数据)传送的,每一串行帧的数据由起始位、数据位、奇偶校验位和停止位组成。 

  (2)同步通信方式 

  同步通信方式中,数据开始传送前用同步字符来指示(常约定1-2个),并由时钟来实现发送端和接收端同步,即检测到规定的同步字符后,就连续按顺序传送数据,直到通信告一段落。 

  (3)查询方式 

  查询方式是定时地查询串口的接收缓冲区,如果接收缓冲区有数据,就读取数据;若缓冲区中没有数据,继续执行,因此会占用大量的CPU时间,它实际上是同步方式的一种派生。 

  (4)事件驱动方式 

  事件驱动方式通过设置事件通知,当所希望的事件发生时,Windows发出通知,这与DOS环境下的中断方式很相似。 

  采用异步方式可以提高系统的整体性能,在对系统强壮性要求较高的场合,建议采用这种方式。查询方式是一种最直接的读串口方式,但定时查询存在一个致命的弱点,即查询是定时发生的,可能发生得过早或过晚。在数据变化较快的情况下,特别是主控计算机的串口通过扩展板扩展到多个时,需定时地对所有串口轮流查询,此时容易发生数据的丢失。虽然定时间隔越小,数据的实时性越高,但系统的资源也被占去越多。事件驱动方式是一种高效的串口读方式,这种方式的实时性较高,特别是对于扩展了多个串口的情况,只有当设定的事件发生时,应用程序得到消息后,才进行相应的处理,避免了数据丢失。事件驱动方式能够更好地处理串行端口通信交互,其优点是程序响应及时,可靠性高。在实时性要求较高的场合建议采用事件驱动方式。 

  1.3 实现步骤 

  利用PC机的串口实现串行通信的一般步骤如下: 

  (1) 打开并配置串口 

  在应用程序中要使用串口进行通信,必须在使用前向操作系统提出资源申请,要求打开串口,为了保证串口通信数据传输的可靠性,串口打开时一般都设置为非共享模式,串口一旦被打开,其他的应用程序将无法打开或使用它。 

  在使用串口进行数据通信前必须对其进行配置,串口配置主要包括波特率、数据位数、停止位数、奇偶校验、发送缓冲区大小、接收缓冲区大小等。 

  (2) 数据读写和超时设置 

  串口打开并配置好后即可对其进行读写操作了,对串口的读写操作可采用查询、同步、异步和事件驱动等方式。 

  在串口通信时如果数据传输突然中断,对串口的读写操作可能会进入无限期的等待状态,为避免这种情况发生,必须设置串口读写操作的等待时间,等待时间超过后,串口的读写操作将被主动放弃,这样即使数据传输突然中断,程序也不会被挂起或阻塞。 

  (3) 关闭串口 

  在串口使用完后应将其关闭,否则如果没有关闭串口,该串口将始终处于打开状态,其他的应用程序就无法打开或使用它。 

  2 PowerBuilder编程中实现串行通信的方法 

  利用PowerBuilder实现串行通信常用的方法主要有四种:一是使用通信控件,如MSComm控件;二是调用Win32 API函数;三是利用串行通信组件;四是调用DLL(动态连接库)实现串行通信编程,下面就四种方法分别加以讨论。 

  2.1 使用MSComm通信控件实现串行通信编程 

  2.1.1 MSComm 控件 

  在PowerBuilder中可采用Mscomm32.ocx控件实现串行通信编程。串行通信控件Mscomm32.ocx(简称MSComm)是Microsoft公司提供的Windows下串行通信编程的32位ActiveX控件。该控件将串行通信的大部分操作都封装到控件的内部,提供了一系列通信命令的接口属性和事件,它允许建立串行口连接,可以连接到其他通信设备(如Modem)、还可以发送命令、进行数据交换以及监视和响应在通信过程中可能发生的各种错误和事件,从而可以用它创建全双工的事件驱动的通信程序。 

  MSComm控件提供两种处理通信的方式:事件驱动方式和查询方式。查询方式通过检查CommEvent属性值来确定通讯事件和错误。事件驱动方式在串口接收到或发送完指定数量的数据时或状态发生改变时,MSComm通信控件捕获到这些事件和错误,触发OnComm事件,通过检查MSComm控件的CommEvent属性的值来获得所发生的事件和错误代码值,从而执行相应的处理。

2.1.2 MSComm 控件主要属性和事件 

  CommPort:设置并返回通信端口号,选COM1时值为1。 

  Setting:以字符串的形式设置并返回串口通信参数,格式为“波特率、奇偶校验、数据位、停止位”。 

  PortOpen:设置并返回通信端口的状态,属性为True打开串口,为False关闭串口并清除接收和传输缓冲区。 

  InputMode:设置从缓冲区读取数据的格式,0文本形式,1二进制形式; 

  Input:从接收缓冲区读取数据; 

  Output:向发送缓冲区写入数据; 

  InBufferCount:设置接收缓冲区中的字节数; 

  OutBufferCount:设置发送缓冲区中的字节数; 

  InputLen :设置并返回Input属性从接收缓冲区读取的字节数; 

  Rthreshold :当CommEvent 属性为ComEvReceive并产生OnComm之前设置并返回要接收的字符数 

  CommEvent:返回最近的通信事件或错误; 

  OnComm事件:无论何时当 CommEvent 属性的值变化时,就产生 TYPE="audio/mpeg"> 

powerbuilder串口编程的实现

因公司软件产品需要和POS机进行通信,所以笔者研究了一下PB串口编程的实现方式。

PB是一个非常好的数据库管理系统的开发工具,但在web和计算机接口通信等方面PB就不是很好用了。幸好我们有ole和com这些很牛的技术,可以让我们非常容易的使用一些组件的功能,而不用自己去开发去关心底层的业务逻辑。使用PB进行串口编程有两种途径,一种是使用微软提供的通信控件(MScomm控件),另一种是用Win32 API函数。下面主要讲解使用MScomm控件实现串口编程的方法。

串行通信控件Mscomm32.ocx(简称MSComm)是 Microsoft公司提供的Windows下串行通信编程的32位ActiveX控件。该控件将串行通信的大部分操作都封装到控件的内部,提供了一系列通信命令的接口属性和事件,它允许建立串行口连接,可以连接到其他通信设备(如Modem)、还可以发送命令、进行数据交换以及监视和响应在通信过程中可能发生的各种错误和事件,从而可以用它创建全双工的事件驱动的通信程序。MSComm控件提供两种处理通信的方式:事件驱动方式和查询方式。查询方式通过检查CommEvent属性值来确定通讯事件和错误。事件驱动方式在串口接收到或发送完指定数量的数据时或状态发生改变时,MSComm通信控件捕获到这些事件和错误,触发OnComm事件,通过检查MSComm控件的 CommEvent属性的值来获得所发生的事件和错误代码值,从而执行相应的处理。

1、Mscomm32.ocx的注册

我们可以单独制做一个注册程序,并打包到您的应用程序中。如果需要安装的目标计算机已经有“Mscomm”控件,则不需要进行任何工作。如果没有“Mscomm”控件,则需要运行这个注册程序。


程序的PB编码如下:
RegistrySet(“HKEY_CLASSES_ROOT/Licenses/4250E830-6AC2-11cf-8ADB-00AA00C00905″,”",RegString!,”kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun”) 
run(“regsvr32   mscomm32.ocx”) 
messagebox(‘提示’,'请重新启动计算机’) 
这只是简单的编码,并且mscomm32.ocx文件在当前运行目录,注册成功即出现系统消息。为了使界面更友好,您可以做一步修饰,例如“run(“regsvr32/s   mscomm32.ocx”)”,这样就可以使屏幕上不出现系统消息了。
您还可以利用API函数,通过“ExitWindowsEx”函数(user32.dll)可以实现重新启动Windows系统。
2、使用Mscomm32控件进行串口通信
Mscomm32控件的常用属性如下:
CommPort:设置或返回串行端口号,缺省为1 
Setting:设置或返回串行端的波特率、奇偶校验位、 数据位数、停止位。缺省值为“9600,N,8,1″。 
PortOpen:设置它为True则打开端口,设置它为False则关闭端口。 
InBufferSize:设置或返回接收缓冲区的大小,缺省为1024 字 节。 
InBufferCount:返回接收缓冲区内的等代读取的字节个数,设属性为0清除接收缓冲区。 
OutBufferSize:设置或返回发送缓冲区,缺省为512字节。 
OutBufferCounter:返回发送缓冲区内等待发送的字符数,可用0来清空缓冲区。 
Output:向发送缓冲区传送数据 
RThreshold: 该属性确定当接收缓冲区内字节个数达或超过该值后就产生代码为ComEventReceive 
的OnComm事件,设置位0,则不产生OnComm事件。 
CommEvent:有通讯错误或事件发生时产生OnComm事件,CommEvent事件的值可以用来确定引 
发OnComm事件的具体的错误或事件常用的有以下几种(更详细的资料可参考MSComm控件帮助文件) 
ComEventbreak:接受到中断信号 
ComEventFrame:硬件检测到帧错误。 
ComEventRxOver:接收缓冲区溢出。 
ComEventTxFull:发送缓冲区溢出。 
ComEventReceive:接受到规定的字符数。 
InputLen:设置或返回接收缓冲区内用Input读入的个数。若取0,则读取整个缓冲区的内容。 
Input:返回并删除接受缓冲区的数据。 

 

3、pb的实例代码

我们可以根据我们程序的需要来设置上面的属性。Mscomm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。由于笔者只需要和POS机进行简单的通信,所以我使用比较简单的查询方式。对于查询方式,我们只要使用PB操作Mscomm32的output和input两个属性就可以了。下面是示例代码:

 

oleobject i_ole_comm  //声明ole对象,用来连接Mscomm控件

i_ole_comm=create oleobject

vresult=i_ole_comm.connecttonewobject(‘mscommlib.mscomm’)

//下面初始化mscomm32的参数,并打开串口

if p_comport=1 then

i_ole_comm.CommPort = 1 //1代表com1口,2代表com2口

elseif p_comport=2 then

i_ole_comm.CommPort = 2

else

i_errcode=-1

i_errtext=’uo_rs232ld.f_setdevice:打开串口com’+string(p_comport)+’端口出错,请确认此端口存在且没有被其他程序使用’

return i_errcode

end if

i_ole_comm.Settings=”9600,n,8,1″    //波特率这里设置成了9600,这个要与pos机设置的波特率一直

i_ole_comm.InputLen=0

i_ole_comm.InBufferSize=90

i_ole_comm.OutBufferSize=60

i_ole_comm.SThreshold=0

i_ole_comm.RThreshold=9

i_ole_comm.Handshaking=0

i_ole_comm.InBufferCount=0

i_ole_comm.DTREnable=true

if not i_ole_comm.PortOpen then

i_ole_comm.PortOpen=True

end if

//向串口发送报文

i_ole_comm.OutPut=“Hello world”

//接受串口报文,循环等待接收pos机上传的报文,超时则返回

Do while true

Yield()

sleep(20)

vinput +=i_ole_comm.Input  //从Com端口取数据

if Pos(vinput,vend) > 0 then exit //如果存在消息结束符,则推出循环

loop

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章