Visual Foxpro中的多用户及数据缓冲题目
发布时间:2018-08-17 23:53:56 所属栏目:电商 来源:站长网
导读:主题:Visual Foxpro中的多用户及数据缓冲题目 绍 许多狐友(Foxers)都是从Dbase―FoxBase―Foxpro―VFP这样一条路走过来的,假如说从FoxBase 到Foxpro是一次奔腾,那么从Foxpro到VFP就是一次升华。漫漫编程路上的两次大变革都陪伴着进级的欢快与顺应的痛
主题:Visual Foxpro中的多用户及数据缓冲题目 绍 许多狐友(Foxers)都是从Dbase―FoxBase―Foxpro―VFP这样一条路走过来的,假如说从FoxBase 到Foxpro是一次奔腾,那么从Foxpro到VFP就是一次升华。漫漫编程路上的两次大变革都陪伴着进级的欢快与顺应的疾苦,惯性思想每每使我们轻易忽略新版本的新内容。我们先来看看下面这个在表单中编辑记录的例子: 在Foxpro 2.X期间,我是这样计划的: 1、 在屏幕上安排与表中字段对应的文本框(TEXT)控件,用来存放响应的内存变量(如M.CUST_IDT和M.NAME等); 2、 当用户将表的指针定位到某一特定记录时(好比按了"下一个记录"按钮),就用scatter memvar 语句把该记录的全部字段传给响应的内存变量,再用show get来革新屏幕上的文本框中表现的值。在这一时候,用户是不能编辑这些变量的(此时文本框可能被配置为不行用(Disabled),可能其when子句返回的是.F.值),由于用户处在"赏识"状态。 3、 当用户选择了"编辑"按钮时,措施就锁定该记录(假如无法锁定,则表现提醒信息),然后检测每个字段值和响应的内存变量值(假若有差异的,声名必然是有其余用户在我们进入编辑状态后修改并生涯了记录,在这种环境下,要表现提醒信息),之后再用scatter memvar和show get语句革新,这样用户就看到记录中的当前值了; 4、 假如全部字段和响应的内存变量完全匹配,就把变量地址的文本框控件都配置为可用(Enabled)或都让when子句返回.T.,以便让用户可以来编辑这些变量; 5、 当用户选择了"生涯"按钮时,按照必然的法则对输入的数据举办检讨,然后用gatter memvar语句将内存变量写回到记录中,并对记录解锁(unlock),再把全部的内存变量地址文本框配置为不行用(Disabled),可能让其when子句返回.F.值,这时,用户又回到了"赏识"状态。 请留意,在这一进程中我们没有直接读写记录,而是先将各字段值赋给同名内存变量,再让用户编辑这些内存变量,假如统统正常再把这些内存变量写回到记录傍边。之以是用这种要领首要是为了掩护表,假如不切合验证法则,就不应承数据回存到表中。另一点要留意的就是,当用户编辑记录时要对记录加锁(lock),这样就防备了其余用户在统一时刻编辑统一笔记录。可是,这种要领有一个很大的弱点:假设一个用户开始编辑某一记录,在他按下"生涯"按钮前,记录一向处于锁定状态,假云云时该用户有事暂且外出,如午餐,那么其余用户就不能对该记录举办编辑了L。 虽然,你可以不在进入"编辑"状态时加锁,而只在"生涯"记录之前加锁,生涯完后顿时解锁,这样可以使记录被锁按时刻最短,以便其余用户有充实的时刻编辑该记录。可是这也有弱点,试想:假如用户编辑了内存变量,这后点击"生涯",可假如其余用户在你点"生涯"之前也编辑了这笔记录,而且还没生涯,这时会产生什么征象呢?你的生涯要包围他人的修改吗?要放弃你的修改吗?这些都是我们要在计划时当真思量的题目。 我们云云久有居心地计划,其目标都是为了掩护数据。假如你写的措施只是你一人行使,那计划起来也许会简朴得多:你可以直接读取记录中的字段,好比你可以直接在屏幕中browse一个表,这样你输入的内容就直接写进记录了。可是,我们不能包管那些最终用户也象您一样都清晰能输入什么不能输入什么,我们不得不在用户与数据表之间成立一个"防火墙"来掩护数据。在Foxpro 2.X中建设这样的"防火墙"要写一大堆的代码! 值得我们兴奋的是,VFP提供了内建的"防火墙"机制,它有两方面的浸染:一是可直接读取记录,二是只应承通过全部检讨法则的数据被写回。这一机制就是缓冲。 缓冲 在适才我们讲到的例子中,是通过内存变量存贮记录内容,这种要领可以被以为是手工成立了一个数据缓冲器,通过行使scatter memvar把数据从记录中传送到"缓冲"中,再用gather memvar从"缓冲"中传回到记录。 VFP不只能自动举办单笔记录的缓冲(称为行缓冲或记录缓冲),并且还支持另一种范例的缓冲,即表缓冲,表缓冲可通过缓冲器存取多笔记录。行缓冲一样平常用于一次存取一个记录时,这种机制广泛应用于数据录入,就象前文提到的那样:用户可以在表单中表现或编辑单笔记录。表缓冲则合用于一次更新多笔记录,好比一张订货单的明细录入屏幕,通过对物品明细表行使表缓冲,可以应承用户编辑多条明细记录,最后一次性地将全部明细记录生涯或放弃。 除了两种缓冲机制,VFP尚有两种锁定机制。前文报告的那种在Foxpro 2.X中的加锁方法被称为守旧式锁定法(或气馁锁定法)――当用户选择"编辑"时加锁,直到用户选择了"生涯"后再解锁。这种加锁机制确保了当本用户修改记录时其余用户都不能修改该记录,但这样做有利有弊,视详细环境而定。前文所讲的另一种加锁方法叫做开放式加锁法(或乐观锁定法)――只有在写回记录时才锁定该记录,然后顿时解锁。这种加锁机制固然使记录最大时刻内可给此外用户行使,但我们必需处理赏罚当两个用户同时编辑记录时所造成的斗嘴。正如我们下面将要看到的,这对付VFP来嗣魅真是太简朴了,在VFP中大大都的环境下都选用开放式缓冲机制。 由于在VFP中记录可以被自动缓冲,以是就不必再用"人工缓冲"机制了,换句话说,此刻我们可以直接读记录中的字段而不必体谅为每个字段设内存变量。要生涯修改,我们只要简朴地汇报VFP将缓冲器中的内容写到表中即可,如果打消修改,汇报VFP不写入即可。过会儿我们将看到这是怎样操纵的。 当打开一个表时,VFP建设一个"姑且表"(cursor)作为缓冲器,这个"姑且表"用来界说表的属性。对付当地表来说,"姑且表"的独一属性是用来界说缓冲方法的的,视图和长途表尚有一些本文接头范畴之外的其余属性,这些属性的值用CursorSetProp()函数配置,用CursorGetProp()取得。我们过会儿将看到怎样行使这些函数。 当追加记录时,表缓冲有一个风趣的特征:跟着记录添加到缓部器中,它们被赋予一个负记录号,第一个插手的记录,recno()返回值为-1,第二个返回值为-2,依此类推。你可以用一个带负数的go呼吁在缓冲中定位到追加的记录上。这在处理赏罚记录号时很有效,好比为了确认变量InRecno是否为一个可用的记录号,在缓冲状态下,要检测between(InRecno,1,reccount()) OR InRecno<0 而不能只用between(InRecno,1,reccount())。 行使缓冲 缺省环境下缓冲器是封锁的,这种环境下在更新表时VFP和Foxpro 2.X是一样的,要行使缓冲你必须将它打开。缓冲合用于自由表及数据库中的表。要用缓冲还要set multilocks on,由于multilocks缺省值是OFF,假如你忘了配置其值为ON,会呈现错误信息。你可以把multilocks=ON插手到CONFIG.FPW文件中,或是用"器材"栏下的"选项"成果生涯其值为ON。 我们通过cursorsetprop(‘Buffering’,<n>,<Alias>)来界说缓冲方法。假如是对当前表配置缓冲,不愿界说<Alias>,按照你想要的缓冲及锁定方法<n>为下列值: 缓冲及锁定法 <n>值 无缓冲 1 守旧式行缓冲 2 开放式行缓冲 3 守旧式表缓冲 4 开放式表缓冲 5 譬喻,要将当前表配置为开放式行缓冲,用cursorsetprop(‘Buffering’,3),要取适合前正打开的表的缓冲方法,用cursorgetprop(‘Buffering’)。 要配置一个表单的缓冲方法,你可以在表单的Load变乱顶用cursorsetprop()界说全部用到的表,但最好的要领是直接配置表单的BufferMode属性来抉择是开放式照旧守旧式(缺省值为"无"),这样配置后,该表单就会自动对绑定到网格(Grid)中的表行使表缓冲,对其余表则行使行缓冲。假如你的表单行使了数据情形,你可以对某一个表的BufferModeOverride属性按你的意图配置缓冲,以代替表单的BufferMode属性。 假若有效户正在修改缓冲记录中的数据(此时用户处在"编辑"状态),你不只可以取得他们输入到每个字段中的值,还能取得每个字段的初始值和当前值(此值为磁盘中的现实值),为此VFP提供了oldval()和curval()函数。 要获得: 行使: 用户输入值(缓冲的数据) <fieldname> OR <alias.fieldname> 用户未做任何窜改之前的值 Oldval(‘<fieldname>’) 当前记录中的值 Curval(‘<fieldname>’) 注: curval()和oldval()仅用于开放式缓冲。 你也许搞不懂curval()返回值和oldval()返回值有什么差异,假如是在单用户措施中,二者之间是没什么区别,可是假如是在收集中,在开放式锁定下,很也许在本用户编辑一笔记录时,另一个用户也编辑统一笔记录,并在本用户"生涯"之前举办了"生涯",下面是一个例子: 郑某将CONTACTS.DBF指针定位到第2笔记录,并点击了"编辑"按钮: 字段 缓冲值 初始值Oldval() 当前值Curval() 姓名 李达 李达 李达 公司名称 狐友技能开拓公司 狐友技能开拓公司 狐友技能开拓公司 然后,郑某将公司名称改为"狐友俱乐部",但还没有生涯记录: 字段 缓冲值 初始值Oldval() 当前值Curval() 姓名 李达 李达 李达 公司名称 狐友俱乐部 狐友技能开拓公司 狐友技能开拓公司 就在此时,于某也将CONTACTS.DBF指针定位到第2笔记录,并点击了"编辑"按钮,他改变了公司名称为"猎狐者俱乐部",并生涯。此时在郑某的呆板上会看到如下功效: 字段 缓冲值 初始值Oldval() 当前值Curval() 姓名 李达 李达 李达 公司名称 狐友俱乐部 狐友技能开拓公司 猎狐者俱乐部 留意:在上表中CONTACTS.公司名称、oldval(‘公司名称’)以及curval(‘公司名称’)将返回差异的值。会见记录中各字段的初始值、缓冲值和当前值,你可以: l 通过较量缓冲值和初始值来确定哪些字段被用户修改了; l 通过较量初始值和当前值来检测在开始编辑后,收集中是否有其余用户修改了统一笔记录。 假如你不体谅初始值和当前值,而只是但愿检测到某个字段中的内容是否被修悔改,可以用getfldstate()函数。这个函数返回一个数值,指出当前记录是否被做了修改。Getfldstate()按以下名目挪用: getfldstate( <fieldName> | <FieldNumber> [ , <Alias> | <WorkArea> ] ) 返回值及其意义如下表所示: 返回值 意义 1 没改变 2 字段被编辑可能记录的删除标志被改变 3 添加了一条新记录但没编辑字段,以及记录的删除记录未改变 4 添加了一条新记录并编辑了字段,可能记录的删除标志被改变 记录的删除标志被改变,是指删除记录或规复(recall)记录。值得留意的是:对记录删除后又马长举办了规复,尽量对记录来说没影响,可是其删除标志被改变过,因此,getfldstate()函数会返回2或4。 假如你没有界说别名或事变区,getfldstate()将对当前打开的表举办操纵。将<FieldNumber>界说为0,该函数返回当前记录的添加及删除状态,假如界说为-1,将返回一个字符串,在这个字符串中,第一个数字反应整个表的状态,往后每个数字返映的是各字段的状态。 以我们前面讲到的环境为例,在郑某编辑第2笔记录时,getfldstate(-1)将返回"112",第一个数字"1"声名记录没有添加或删除,第二个数字"1"声名第一个字段(姓名)没有改变,第三个数字"2"声名第二个字段(公司名称)内容改变了。 缓冲记录的写回 我们还继承适才的例子。此刻假设郑某点击了"生涯"按钮,我们应该奈何将缓冲中的数据写到记录中(更新表)呢?对付行缓冲来说,当你移动记录指针或挪用tableupdate()函数时,表就会被更新。对付表缓冲来说,移动记录指针并不会引起表的更新(由于它是多记录被同时缓冲),以是凡是环境下只能挪用tableupdate()函数来更新表。对付行缓冲最好也用tableupdate()函数,由于这样更好地节制措施的去处。 假如缓冲器中的内容被正确地写入到记录中,tableupdate()返回.T.值,假如记录缓冲没有改变(用户没有编辑任何字段、添加记录或改变记录的删除状态),此时,tableupdate()也返回.T.,尽量现实上什么也没有做。 Tableupdate()可以带几个参数: Tableupdate( <AllRows>,<Forced>,<Alias>|<Workarea> ) 第一个参数指明哪些记录被更新:设为.F.,则只更新当前记录,若为.T.,则更新全部记录(仅影响表缓冲)。假如第二个参数是.T.,那么其余用户的任何修改将被当前用户的修改所包围。假如没界说第三个参数,tableupdate()将更新当前表。 奈何打消用户所做的修改呢?对付用内存变量的要领,可以再次用scatter memevar 语句从磁盘上的数据规复到内存变量中,而对付缓冲来说,用tablerevert()函数即可到达同样成果。 错误处理赏罚 我们继承"郑某和于某"的例子,当郑某点击"生涯"按钮后,代码将执行tableupdate()函数以把缓冲中的数据写入记录。请记着,在郑某编辑记录时于某已经修改了统一笔记录并做了生涯。当郑某点击"生涯"时,tableupdate() 将返回.F.,声名它不能将缓冲写入记录中,为什么会是这样呢? VFP在以下几种环境下无法将缓冲写入记录: l 当一个用户编辑记录时,其余用户修改并生涯了该记录(正如我们例子中的那种环境)。VFP自动对每个字段的oldval()值和curval()值举办较量,假如检测到任何差异,就会发生斗嘴。 l 用户输入了一再的主索引或候选索引值。 l 违反了某个字段或表的验证法则,可能不支持null的字段呈现了null值。 l 某个触发(trigger)失败。 l 其余用户锁定了该记录。 l 其余用户删除了该记录。 当tableupdate()失败时,我们必需抉择下一步做什么,并且,假如你的措施在编辑记录时应承用户点击"下一个"或"上一个"按钮,而这两个按钮中又没有挪用tableupdate()的话,你必需得处理赏罚在自动生涯时将会产生的错误。在这两种环境下,将措施指定到恰当的位置就是错误陷阱处理赏罚措施。 Visual Foxpro中的多用户及数据缓冲题目(下) -------------------------------------------------------------------------------- 2000-10-6 17:07:00 在VFP中错误处理赏罚已经获得改造。早年处理赏罚错误陷阱的要领(你如故可以在VFP中继承行使这些要领)是当错误产生时用on error呼吁来抉摘要执行的措施,典范的错误处理赏罚措施是查察error()和message()来确定产生了什么错误,然后采纳响应的举措。 此刻VFP提供了一种自动的错误处理赏罚机制:就是Error要领。假如界说了一个控件或表单中的Error要领,当错误产生时它就被自动执行。aerror()是VFP的一个新增函数,通过转达一个参数,该函数可以建设或更新一个含有以下元素的数组 元素 范例 描写 1 数字 错误号(与error()沟通) 2 字符 错误信息(与message()沟通) 3 字符 假若有一个错误信息参数(与sys(2018)沟通),则返回之(譬喻:一个字段名),无,则返回.NULL. 4 数字或字符 产生错误的事变区。假如没有,则返回.NULL. 5 数字或字符 假如一个触发器失败,返回触发器号(插入为1,更新为2,删除为3),假如没有则返回.NULL. 6 数字或字符 .NULL.(应用于OLE和ODBC错误) 7 数字 .NULL.(应用于OLE错误) 譬喻:aerror(IaERROR)会建设或更新一个称为IaERROR的数组。 以下是VFP在将缓冲写入表时也许产生的一些错误: 错误号# 错误信息 声名 109 记录正由其余用户行使 1539 触发器失败 检测数组的第5个元素可以确定是哪个触发器失败了 1581 字段不接管空值(null) 检测数组的第3个元素可以确定是哪个字段引起的错误 1582 违背了字段的验证法则 检测数组的第3个元素可以确定是哪个字段引起的错误 1583 违背了记录的验证法则 1585 记录已被其余用户修改 1884 违背了索引的独一性 检测数组的第3个元素可以确定是哪个索引标志引起的错误 对付以上这些错误,大部门可以直接处理赏罚:提醒用户题目地址,然后让用户在"编辑"状态下纠正错误或是打消操纵。对付#1585错误(记录已被其余用户修改),有以下几种处理赏罚错误的要领: l 可以提醒当前用户有别人修改了该记录,然后用tablerevert()打消当前用户的编辑内容。我想大都人对这种要了解不兴奋的。 l 可以用tableupdate(.F. , .T.)来强行更新记录,使当前用户的修改包围其余用户修改。这样做,当前用户天然是兴奋的,但其余用户也许就要不满了。:( l 复制一个沟通的表单(在VFP中对统一表单建设多个实例长短常轻易的),在上面表现出其余用户对该记录的修改,这样,当前用户就可以抉择是生涯照旧不生涯其余用户的修改,也就是说,可以用tableupdate(.F. , .T.)强行更新或是用tablerevert()来打消编辑。 有更好的方案来检测我们是否碰着了"真正的"斗嘴,所谓"真正的"斗嘴,是指两个用户在统一时刻修改了统一个字段。假如他们修改的是统一记录的两个差异字段,我们可以只更新当前用户修改的字段,而保存另一个用户修改的字段,使之不受影响。譬喻,在一个订单处理赏罚体系中,一个用户修改了产物先容,而同时另一个用户在对该产物下订单,正在输入数目,这两个修改彼此独立,并没有斗嘴,这时我们不要一次更新整笔记录,而是只更新本身修改的谁人字段,云云一来,两个用户城市感想满足。 以下是实现这一设法的思绪: l 查找oldval()与curval()差异的字段,假若有,声名该字段已被其余用户编辑过,假如该字段的缓冲值与oldval()沟通,声名当前用户并没有修改该字段。这种环境下,我们可以将curval()中的值先传给缓冲值,再更新,这样就可以停止缓冲值包围新值了。 l 查找缓冲值与oldval()差异的字段,这些字段是当前用户修悔改的字段,假如oldval()又便是curval(),声名其余用户没有窜悔改该字段,这种环境下,我们可以安心地包围掉它。 l 假如我们找到的字段,其缓冲值与oldval()差异,但与curval()沟通,这声名两个用户对统一字段做了沟通的修改。这种环境看起来好象不大也许,着实是会产生的。好比有人发来了一个公司的地点变换信息,而恰好有两个用户同时抉择据此来更新记录中的公司地点。由于他们所做的修改内容是沟通的,我们可以包围另一个即可。可是,假如是以统一个数目更新一个量值的话(好比两人同时下订单,且输入了沟通的数目),你就不能简朴地包围字段,应该将此看作为"真正的"斗嘴。 l 假如发明一个字段的缓冲值既差异于oldval()也差异于curval(),并且oldval()与curval()也各不沟通,这声名两个用户都修改了统一个字段,且值不沟通。这种环境才是我们碰着的真正的斗嘴,我们不得不抉择奈何处理赏罚这一斗嘴。 在手工输入存货数目或帐目余额时,有一种也许就是其余用户输入的值对缓冲值会发生影响。好比,假如检测到oldval()是10, curval()是20,声名其余用户将数额已增进了10;假云云刻缓冲值为5,声名当前用户要将数额在原基本(10)上镌汰5,因此新的缓冲值就应该是value+ oldval()- curval(),即便是15,应该用此数来更新字段。 对付日期型字段的斗嘴,就要思量贸易法则或按现实环境处理赏罚。譬喻,在"病人预约时刻"措施中,有一个字段生涯着病人下次预约大夫的时刻,假如该字段两个日期产生斗嘴的话,那么,接近当前日期的谁人日期很也许是正确的。虽然,如果个中一个预约日期比当前日期还要早的话(已经逾期),那就应该取靠后的谁人日期了。 其余范例的字段,出格是字符型和备注型字段,凡是环境下假如不扣问用户以抉择是包围其余用户的修改照旧打消本身的修改的话,则斗嘴欠好办理。只有当用户在屏幕上看到其余用户到底做了什么修改后,他才气做出正确地判定。 以下是办理斗嘴的一些代码(这些代码假设已检测到错误码为#1585,即记录已被其余用户修悔改。) * 检测每一个字段,看哪个产生了斗嘴。 llConflict = .F. for lnI = 1 to fcount() lcField = field(lnI) llOtherUser = oldval(lcField) <> curval(lcField) llThisUser = evaluate(lcField) <> oldval(lcField) llSameChange = evaluate(lcField) == curval(lcField) do case * 其余用户编辑了该字段,而当前用户没编辑,以是直接用新值即可。 case llOtherUser and not llThisUser replace (lcField) with curval(lcField) * 其余用户没有编辑该字段,可能二者做了沟通的修改,因此我们无需做任那里理赏罚。 case not llOtherUser or llSameChange * 两个用户以差异的值修改了该字段。 otherwise llConflict = .T. endcase next lnI * 假如产生了斗嘴,处理赏罚之! if llConflict lnChoice = messagebox('Another user also changed this ' + ; 'record. Do you want to overwrite their changes (Yes), ' + ; 'not overwrite but see their changes (No), or cancel ' + ; 'your changes (Cancel)?', 3 + 16, 'Problem Saving Record!') do case * 包围其余用户的修改。 case lnChoice = 6 = tableupdate(.F., .T.) * 通过发生一个表单实例来查察其余用户的修改内容。 case lnChoice = 7 do form MYFORM name oName * 打消当前用户的修改。 otherwise = tablerevert() endcase * 假如没有产生斗嘴,则强行更新。 else = tableupdate(.F., .T.) endif llConflict 表缓冲的写入 我们前面已经讲到,可以用tableupdate(.T.)将表缓冲中的全部记录一次写入磁盘。与行缓冲一样,假如其余用户修改了表(或是其余什么堕落缘故起因)而不能正确更新表,tableupdate(.T.)将返回.F.值。 前文所讲的错误处理赏罚措施在行缓冲模式下运行精采,由于我们在某一时候只体谅单笔记录。但对付表缓冲来说,我们不得不思量每一笔记录,由于在缓冲区中也许既有修悔改的记录,也有未修悔改的记录,我们奈何知道到底更新哪笔记录呢?假如用tableupdate(.T.)失败(返回.F.),环境就变得越发伟大化:我们不知道错在哪笔记录上!并且有些记录也许被做过"生涯",以是还不止一笔记录会产生斗嘴呢。请不要着急:),VFP新增函数getnextmodified()可以准确地汇报我们想知道的信息:该函数返回下一个被修改记录的记录号。假如返回值为0,声名在缓冲区中没有被修悔改的记录。这个函数吸取两个参数:第一个参数是一个记录号,正是从这个记录号开始向下查找下一个被修改的记录;第二个参数是查找的事变区别名。最被,你应该将0传给第一个参数,这样getnextmodified()就会找到第一个被修改的记录,若要继承找下一个被修改的记录,只要将当前记录的记录号传给第一个参数即可。 下面是在适才处理赏罚斗嘴的措施基本上改造后的代码,它用来处理赏罚表缓冲更新失败时的操纵。 * 先找到第一个被修悔改的记录。 lnChanged = getnextmodified(0) do while lnChanged <> 0 * 移动记录指针并实行锁定它。 go lnChanged if rlock() * 检测每一个字段,看哪个产生了斗嘴。 llConflict = .F. for lnI = 1 to fcount() lcField = field(lnI) llOtherUser = oldval(lcField) <> curval(lcField) llThisUser = evaluate(lcField) <> oldval(lcField) llSameChange = evaluate(lcField) == curval(lcField) do case * 其余用户编辑了该字段,而当前用户没编辑,以是直接用新值即可。 case llOtherUser and not llThisUser replace (lcField) with curval(lcField) * 其余用户没有编辑该字段,可能二者做了沟通的修改,因此我们无需做任那里理赏罚。 case not llOtherUser or llSameChange * 两个用户以差异的值修改了该字段。 otherwise llConflict = .T. endcase next lnI * 假如产生了字段斗嘴,我们可以在此处理赏罚它,与行缓冲差异的是,我们也可以此刻不处理赏罚,由于往后全部记录将被写入,到时会处理赏罚的。 if llConflict lnChoice = messagebox('Another user also changed ' + ; 'record ' + ltrim(str(lnChanged)) + '. Do you want to ' + ; 'overwrite their changes (Yes), not overwrite but see ' + ; 'their changes (No), or cancel your changes (Cancel)?', 3 + 16, ; 'Problem Saving Record!') do case * 假如选择了包围其余用户的修改,在此可以不做处理赏罚,由于往后将一次性更新。 case lnChoice = 6 *通过发生一个表单实例来查察其余用户的修改内容。 &nb 转载! (编辑:河北网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |