??xml version="1.0" encoding="utf-8" standalone="yes"?>
׃股票变化无常Q主力更是绞脑汁和散户斗智斗勇Q所以买入法也没有固定格式,我在q里只简单的介绍几种很有效的Ҏ(gu)Q仅供你借鉴?br>
1、量~法?/strong>思义Q就是当股票在一?#8220;势和条?#8221;下,成交量开始萎~到不能再萎~时Q说明下跌能量消耗已,此时是最好的买入炏V所谓的“势和条?#8221;是讲——这只股运行趋势必L在上升通道或低位震荡中Q当它连l下跌两C天时Q成交量已经萎羃很多Q股hL动范围已l很,盘中也不再见有大的买单,特别是遇到大盘下跌时Q它也不再下跌,q说明这只股到?#8220;?#8221;底,随时有反弹和新的行情发动Q此时就是最价买入点。例?00297??0号到2?Pq箋下跌了四天,切成交量逐步萎羃Q??号就是个最价买炏V?br>
2、前高突破法?/strong>当一只股经q一D|间的上涨Q之后开始进入回调,当经q一D|间的调整Q再ơ开始放量攻d期高Ҏ(gu)Q此时也是买入点。但是这里最难把握的是d的假H破Q很Ҏ(gu)上当Q这需要你自己正确判断。比方说600983??3辑ֈ一个高点后Q??号开始放量攻d期高点,那么2?号就是最价买炏V?00717??号就是一个假H破。我特别一点,最好是出现三次冲击前期高点的股,把握性最大?br>
3、长阳之后等待法?/strong>是当某只股出现长阳甚x涨停ӞW二天它很可能不再连l拉升,而是出现幅的调_此时也是买入点,例如600723??8日就是一个买入点?br>
4、诱I破法?/strong>很多d在进入下一波的大行情中Q往往做最后的qz盘。此时也是最价买入法Q这需要你高超的识盘技巧。例如,600176??1P出现了一条放量的镉KQ其实那是诱I,做出q样的判断是要对q只股票的基本面和技术面都非常熟(zhn)才行?br>
5、大换手率的{待法?/strong>当某只股在低位Q特别强调是低位Q出现大换手率时Q说明主力杀入,你随时可以跟q。例?00178??9?2q箋两天出现过12%的还手率Q之后再出现低点Ӟ你就可以杀入了?/span>
]]>
与TTable、TQuery一PTClientDataSet也是从TDataSetl承下来的,它通常用于多层体系l构的客L。TClientDataSet最大的特点是它不依赖于BDE(Borland Database Engine)Q但它需要一个动态链接库的支持,q个动态链接库叫DBCLIENT.DLL。在客户端,也不需要用TDatabase构gQ因为客Lq不直接q接数据库?br /> ׃TClientDataSet是从TDataSetl承下来的,所以,它支持诸如编辑、搜索、浏览、纠错、过滤等功能。由于TClientDataSet在内存中建立了数据的本地副本Q上q操作的执行速度很快。也正是׃TClientDataSetq不直接q接数据库,因此Q客L序必L供获取数据的机制。在Delphi 4中,TClientDataSet有三U途径获取数据Q?br />.从文件中存取数据?br />.从本地的另一个数据集中获取数据?br />.通过IProvider接口从远E数据库服务器获取数据?br /> 在一个客L序中Q可以同时运用上qCU机制获取数据?
11.1 览和编辑数?/b>
和其他数据集构g一P可以用标准的数据控g昄由TClientDataSet引入的数据集Q当Ӟq需要借助于TDataSource构g?br /> ׃TClientDataSet是从TDataSetl承下来的,所以,凡是其他数据集构件支持的功能QTClientDataSet构g也大致具备。不同的是,TClientDataSet能够在内存中建立数据的副本,因此QTClientDataSet比其他数据集构g增加了一些特D的功能?br />11.1.1 览数据
可以用标准的数据控g昄由TClientDataSet引入的数据集。在q行期,可以调用诸如First、GotoKey、Last、Next和Prior{函数来览数据?br /> TClientDataSet也支持书{֊能,可以用书{来标记某条记录Q以后就可以方便地找到这条记录?br /> 对于TTable、TQuery{数据集构g来说Q只能读RecNo属性来判断当前记录的序受对于TClientDataSet构g来说Q还可以写RecNo属性,使某一序号的记录成为当前记录?br />11.1.2 CanModify属?/b>
TDataSet的CanModify属性用于判断数据集中的数据是否可以修改。CanModify属性本w是只读的,也就是说Q数据是否能够修改不取决于应用程序?br /> 不过QTClientDataSet构g有其Ҏ(gu)性,因ؓTClientDataSet已经把数据在内存中徏立了副本Q因此,应用E序可以军_是否允许修改数据。如果不允许用户修改数据Q只要把ReadOnly属性设为TrueQ此ӞCanModify属性肯定返回False?br /> 与其他数据集构g不同Q修改TClientDataSet构g的ReadOnly属性时Q不需要事先把Active属性设为True?br />11.1.3 取消修改
TClientDataSet传输数据的基本单位称为数据包Q当前的数据包可以由Data属性来讉K。不q,用户Ҏ(gu)据的修改q不直接反映到Data属性中Q而是临时写到一个日志即Delta属性中Q这样做的好处是以后随时可以取消修改?br /> 不过Q这里要说明一点,管用户的修改ƈ没有反映到DataQ当用户在数据控件中看到的却是最C改的数据。如果一条记录被反复修改了多ơ,用户看到的只是最新的数据Q但日志中却记蝲了多ơ?br /> 要取消上一ơ的修改Q调用UndoLastChange函数。UndoLastChange需要传递一个布?yu)类型的参数叫FollowChangeQ如果FollowChange参数设ؓTrueQ光标就Ud被恢复的记录上,如果FollowChange参数设ؓFalseQ光标仍然在当前记录上?br /> ChangeCount属性返回日志中记蝲的修Ҏ(gu)数。如果一条记录被反复修改了多ơ,每调用一ơUndoLastChange能够逐取消上一ơ的修改?br /> UndoLastChange只能取消上一ơ的修改Q如果想一下子取消所有的修改Q首先要选择一个记录,然后调用RevertRecord。RevertRecord从日志中取消所有对当前记录的修攏V?br /> TClientDataSetq有一个SavePoint属性,它能把当前的~辑状态保存v来,以后随时可以q回当时的状态。例如,可以q样保存当前的状态:
BeforeChanges := ClientDataSet1.SavePoint;
以后Q可以这h恢复当时的状态:
ClientDataSet1.SavePoint := BeforeChanges;
应用E序可以保存多处状态,可以恢复其中一个状态,不过Q一旦某个状态被恢复Q在其之后的状态就无效?br /> 如果要一下子取消日志中记载的所有修改,可以调用CancelUpdates函数。CancelUpdates把日志清空Q取消所有的修改?br /> 如果LogChanges属性设为FalseQ用户对数据的修改就会直接反映到Data属性中?
11.1.4 合ƈ修改
要把日志中记载的修改合ƈ到Data属性中Q有两种方式Q具体用哪一U方式,取决于应用程序获取数据的机制。不q,不管是哪U机Ӟ合ƈ后,日志自动被清I?br /> 对于一个从文g中获取数据的E序来说Q只要调用MergeChangeLog函数Q就把日志中记蝲的修改合q到Data属性中。不用担心其他用户同时修改了数据?br /> 对于一个从应用服务器获取数据的E序来说Q就不能调用MergeChangeLog来合q数据,而要调用ApplyUpdates函数QApplyUpdates会把日志中记载的修改传递给应用服务器,待应用服务器成功地把数据更新了数据库服务器后Q才会合q到Data属性中?br />11.1.5 U错
TClientDataSet支持U错功能。一般情况下Q需要自己徏立纠错规则,以便对用戯入的数据q行U错?br /> 此外Q如果获得了IProvider接口的话Q还可以从远E服务器引入U错规则?br /> 有时候,客户端可能需要暂时禁止纠错,因ؓ客户端从应用服务器检索数据是分阶D进行的Q在所有的数据索完毕之前,有些U错规则很可能会报错?
要暂时禁止纠错,可以调用DisableConstraintsQ要重新允许U错Q可以调用EnableConstraints函数。DisableConstraints和EnableConstraints实际上都是作用于一个内部的计数?br />11.2 ??/b>
使用索引有这么几个好处:
.在数据集中定位记录比较快?br />.能够在两个数据集之间建立Lookup或Master/Detail关系?br />.可以对记录排序?br /> 在多层体pȝ构中Q当客户E序从应用服务器索数据时Q它同时获得了默认的索引。默认的索引叫DEFAULT_ORDERQ可以用这个烦引排序,但不能修Ҏ(gu)删除q个索引?br /> 除了默认的烦引外QTClientDataSetq对日志中记载的记录自动建立了一个副索引叫CHANGEINDEX。与DEFAULT_ORDER一P不能修改或删除这个副索引?br /> 另外Q还可以使用数据集中已徏立的其他索引Q或者自己徏立烦引?br />11.2.1 创徏一个新的烦?/b>
要创Z个新的烦引,可以调用AddIndex。AddIndex需要传递若q个参数Q?br /> 一是Name参数Q用于指定烦引名。在q行期切换烦引时需要用到烦引的名称?br /> 二是Fields参数Q它是一个字W串Q用于指定烦引中的字D名Q彼此之间用分号隔开?br /> 三是Options参数Q用于设|烦引的选项Q包含ixDescending元素表示按降序排列,包含ixCaseInsensitive元素表示大小写不敏感?br /> 四是DescFields参数Q它也是一个字W串Q用于指定若q个字段名,q些字段按照降序排列?br /> 五是CaseInsFields参数Q它的作用与DescFields参数cMQ包含在CaseInsFields参数中的字段对大小写不敏感?br /> 六是GroupingLevel参数Q用于指定分l别,其g能超q烦引中的字D|?br /> 下面的代码创Z一个烦引:
If Edit1.Text <> '' and ClientDataSet1.Fields.FindField(Edit1.Text) then
Begin
ClientDataSet1.AddIndex(Edit1.Text+'Index',Edit1.Text,
[ixCaseInsensitive],'','',0);
ClientDataSet1.IndexName := Edit1.Text + 'Index';
End;
Z避免创徏一个烦引,可以临时用IndexFieldNames属性来指定若干个字D,让数据集按这些字D|序?br />11.2.2 删除和切换烦?/b>
要删除一个先前创建的索引Q可以调用DeleteIndexq指定要删除的烦引名U。注意:DEFAULT_ORDER和CHANGEINDEX不能删除?br /> 如果建立了多个烦引,可以L选择其中的一个烦引,q就要用到IndexName属性?br />11.2.3 用烦引把数据分组
选择了一个烦引后Q数据集自动按其中的字D进行排序。这P临近的记录往往在关键字D上含有相同的倹{例如,假设有一个表是这LQ?br />SalesRep Customer OrderNo Amount
1 1 5 100
1 1 2 50
1 2 3 200
1 2 6 75
2 1 1 10
2 3 4 200
可以看出QSalesRep字段的值有重复的。对于SalesRep字段的gؓ1的来_Customer字段的g有重复的。这是_可以按SalesRep字段分组Q进而再按Customer字段分组。显Ӟq里的分l别是不同的,按SalesRep字段建立的分l属于第一U,按Customer字段建立的分l属于第二。实际上Q分l别取决于字段在烦引中的顺序?br /> TClientDataSet可以军_是否按照分组U别来显C录的倹{例如,也许想以下面q种形式昄数据Q?br />SalesRep Customer OrderNo Amount
1 1 5 100
2 50
2 3 200
6 75
2 1 1 10
2 3 4 200
要判断当前记录某一U的什么位|,可以调用GetGroupState函数。GetGroupState函数需要传递一个参敎ͼ用于指定分组U别?br />11.3 ???D?/b>
与其他数据集一P也可以在TClientDataSet建立的数据集中增加计字Dc计字D늚值是Z同一个记录中的其他字D计出来的?br /> 在其他数据集中,只要用户修改了数据或当前记录发生改变Q就会触发OnCalcFields事gQ换句话_计算字段的值就被计一ơ?br /> TClientDataSet引入了“内部计字D”的概念。与一般的计算字段不同的是Q内部计字D늚值将随其他字D늚g起存取,q样Q只有当用户修改了数据才会触发OnCalcFields事gQ如果仅仅改变了当前记录Q不会触发OnCalcFields事g。也是_内部计算字段的值需要重新计的Z大大减少?br /> 在处理OnCalcFields事g的句柄中Q首先要判断State属性。如果State属性返回dsInternalCalcQ此旉要计内部计字D늚倹{如果State属性返回dsCalcFieldsQ此旉要计一般的计算字段的倹{?br />11.4 l???/b>
TClientDataSet增加了统计的功能Q它可以Z分组自动计算d、^均、计数、最大、最倹{当用户~辑数据Ӟq些l计g自动跟着变化?br />11.4.1 指定l计方式
要指定怎样q行l计Q就要用到Aggregates属性。这个属性是一个TAggregates对象Q它用于理一lTAggregate对象?br /> 在设计期Q可以单击Aggregates属性边上的省略h钮打开如图11.1所C?br />的编辑器?br /> ?1.1 理一lTAggregate对象
单击按钮可以增加一个TAggregate对象Q单L钮可以删减一个TAggregate对象Q单L钮可以把TAggregate对象前移Q单L钮可以把TAggregate对象后移?br /> 可以用字D늼辑器专门创徏一个用于表辄计值的字段Q该字段的类型必L“Aggregate”。Delphi 4会自动创Z个TAggregate对象Qƈ加到Aggregates属性中。选择一个TAggregate对象QObject Inpector显C对象的属性?br /> 其中QExpression属性用于指定统计表辑ּQ例如:
Sum(Field1)
也可以是比较复杂的表辑ּQ?br />Sum(Qty * Price) - Sum(AmountPaid)
在表辑ּ中,可以使用下列l计q算W:
.Sum计算一l数据的d?br />.Avg计算一l数据的q_倹{?br />.Count计算一l数据中的非I值的个数?br />.Min计算一l数据的最倹{?br />.Max计算一l数据的最大倹{?br /> 除了上述几个l计q算W外Q还可以使用qo条g中所能用的q算W,但不能嵌套。在一个表辑ּ中,可以混合出现几个l计值或帔RQ但不能混合出现l计值和字段?br /> Sum(Qty * Price){合法}
Max(Field1) - Max(Field2){合法}
Avg(DiscountRate) * 100{合法}
Min(Sum(Field1)){非法Q不能嵌套}
Count(Field1) - Field2{非法Q统计值和字段不能混合出现在一个表辑ּ中}
11.4.2 指定分组
默认情况下,l计值是Z数据集中所有的记录计算出来的。不q,也可以针对一部分记录计算l计|q就需要事先徏立分l?br /> 前面在介l烦引时已经提到分组的概c可以通过IndexName属性和GroupingLevel属性来选择使用哪个索引以及最大的分组U别?br /> 例如Q假设有一个表是这LQ?br />SalesRep Customer OrderNo Amount
1 1 5 100
1 1 2 50
1 2 3 200
1 2 6 75
2 1 1 10
2 3 4 200
如果要按SalesRep字段分组Qƈ且指定其中的W一U,E序代码应当q样写:
Agg.Expression := 'Sum(Amount)';
Agg.IndexName := 'SalesCust';
Agg.GroupingLevel := 1;
Agg.AggregateName := 'Total for Rep';
11.4.3 怎样获取l计?/b>
要获取统计|可以调用TAggregate对象的Value函数。如果统计值是Z数据集中所有的记录计算出来的,随时可以调用Value函数。如果统计值是Z分组计算出来的,必须保证当前记录正好位于该分l内。因此,在调用Value之前Q最好先调用GetGroupState函数看看当前记录是否位于该分l内?br /> 要在数据控g中显C统计|必须事先在字D늼辑器中创Z个永久字D对象,该字D늚cd必须是Aggregate?br />11.5 ???/b>
通过Data属性可以访问客L序从应用服务器检索到的数据。程序示例如下:
Procedure TForm1.Button1Click(Sender: TObject);
Begin
ClientDataSet1.Data := ClientDataSet1.Provider.DataRequest(FilterEdit.Text);
End;
11.5.1 直接对Data属性赋?/b>
前面讲过Q客L序既可以通过IProvider接口获取数据Q也可以从另一个数据集获取数据Q后者就是通过Data属性赋值的。程序示例如下:
ClientDataSet1.Data := ClientDataSet2.Data;
一旦Data被赋|可以用标准的数据控件显C些数据?br /> 注意Q当从另一个数据集获取数据Ӟ另一个数据集的日志也被复制q来Q但不包括原来的范围和过滤条件?br /> 如果要从另一个基于BDE的数据集中获取数据,可以通过数据集构件的Provider属性,E序CZ如下Q?br /> ClientDataSet1.Data := Table1.Provider.Data;
如果要从一个自定义的数据集获取数据Q首先要创徏一个时的TProvider构gQ然后设|其DataSet属性指定这个自定义的数据集。程序示例如下:
TempProvider := TDataSetProvider.Create(Form1);
TempProvider.DataSet := SourceDataSet;
ClientDataSet1.Data := TempProvider.Data;
TempProvider.Free;
11.5.2 在数据包中加入自定义的信?/b>
可以把自定义的信息加到数据包中。当把数据保存到文g或流中时Q这些自定义的信息也保存到文g或流中。如果把数据包直接赋值给另一个数据集的话Q这些自定义的信息也被复制?br /> 要把自定义的信息加到数据包中Q可以调用SetOptionalParam函数。要从数据包中检索自定义的信息,可以调用GetOptionalParam。程序示例如下:
Procedure TAppServer.Provider1UpdateData(Sender: TObject; DataSet: TClientDataSet);
var
WhenProvided: TDateTime;
Begin
WhenProvided := DataSet.GetOptionalParam('TimeProvided');
...
End;
11.5.3 克隆另一个数据集
调用TClientDataSet的CloneCursor函数可以获得一个数据集的完全相同的副本。它与直接通过Data属性赋值是有区别的?br /> 区别之一Q数据在两个数据集之间是׃n的,修改其中一个将同时修改另一个?br /> 区别之二Q除了数据外QCloneCursor函数q复制了一些属性和事gQ这取决于Reset和KeepSettings参数怎样讄?br /> CloneCursor函数需要传递三个参敎ͼ其中QSource参数指定源数据集QReset参数和KeepSettings参数用于讄除了数据外是否还要复制下列属性和事gQFilter、Filtered、FilterOptions、OnFilterRecord、IndexName、MasterSource、MasterFields、ReadOnly、RemoteServer、ProviderName、Provider?br /> 如果Reset和KeepSettings参数都设为FalseQ源数据集的上述属性和事g都将被复制给目标数据集。如果Reset参数设ؓTrueQ目标数据集的上q属性和事g都将被清I。如果Reset参数设ؓFalseQ而KeepSettings参数设ؓTrueQ目标数据集的上q属性和事g不变Q不q,必须保证q些属性和事g与克隆后的数据相宏V?br />11.6 与应用服务器通讯
在多层体pȝ构中Q客L序通过IProvider接口与应用服务器交换数据。这一章介l怎样在客L获得IProvider接口、怎样向应用服务器传递参数、怎样向应用服务器h数据、怎样把用户对数据的修改写到数据库中?br />11.6.1 怎样在客L获得IProvider接口
在单层应用程序以及工作在“公文包”模式下的多层应用程序中Q不需要用到IProvider接口。而在多层体系l构中,客户E序要与应用服务器交换数据,首先必须获得IProvider接口Q这p用到RemoteServer属性和ProviderName属性?br /> RemoteServer属性用于指定客L的MIDASq接构g。MIDASq接构g又称Data BrokerQ用于徏立和l护与应用服务器的连接?br /> 在设计期Q正设|了RemoteServer属性后Q就可以在对象观察器中ؓProviderName属性选择一个|实际上就是选择应用服务器上的一个TProvider构g?br />11.6.2 向应用服务器传递参?/b>
客户E序可以向应用服务器传递参敎ͼq些参数实际上是传递给应用服务器上的TQuery构g或TStoredProc构g。既可以在设计期也可以在q行期设|参数?br /> 在设计期Q可以单击Params属性边上的省略h钮,打开一个如?1.2所C的~辑器?br /> ?1.2 讄参数
单击按钮可以增加一个参敎ͼ单击按钮可以删减一个参敎ͼ单击按钮可以把一个参数前U,单击按钮可以把一个参数后UR?br /> 选择一个参敎ͼ对象观察器将昄该参?TParam对象)的属性?br /> 在运行期可以调用TParams的CreateParam函数来创Z个参数。例如,下面的代码创Z一个参数叫CustNoQ它的用类型是ptInputQ数据类型是ftIntegerQ它的D?05?br />With ClientDataSet1.Params.CreateParam(ftInteger, 'CustNo', ptInput) Do
AsInteger := 605;
讄好参C后,如果TClientDataset的Active属性是FalseQ只要把Active属性设为TrueQ这些参数将被自动传递给应用服务器。如果Active属性已lؓTrueQ就要调用SendParams函数把参C递给应用服务器?br /> 注意Q传递给应用服务器的参数必须与TQuery构g或TStoredProc构g的参数匹配,包括名称、数据类型和参数cd?br />11.6.3 怎样向应用服务器h数据
TClientDataSet提供了两个属性和三个Ҏ(gu)Q用于怎样向应用服务器h数据Q?br /> 一是FetchOnDemand属性。如果这个属性设为TrueQTClientDataSet会根据需要自动检索附加的数据包,例如BLOB字段的值或者嵌套表的内宏V如果这个属性设为FalseQ程序需要显式地调用GetNextPacket才能获得q些附加的数据包?br /> 二是PacketRecords属性,用于讄一个数据包中最多可容纳的记录数Q设?1表示一个数据包可以容纳数据集的所有记录?br /> 三是GetNextPacket函数Q用于向应用服务器检索下一个数据包Qƈ把检索到的数据包d到前一ơ检索到的数据包的后面。这个函数返回实际检索到的记录数?br /> 四是FetchBlobsq程Q用于从应用服务器检索BLOB字段的倹{如果FetchOnDemand属性设为TrueQ就没必要调用FetchBlobs函数?br /> 五是FetchDetailsq程Q用于检索嵌套表中的数据。如果FetchOnDemand属性设为TrueQ就没必要调用FetchDetails函数?br />11.6.4 更新数据?/b>
在多层体pȝ构中Q用户在客户端修改了数据后,需要把最新的数据写到数据库中Q这p调用TClientDataSet的ApplyUpdates函数?br /> ApplyUpdates只需要传递一个参数叫MaxErrorsQ用于指定一个整敎ͼ当遇到无法更新的记录过q个数时Q此ơ更新就中止。如果MaxErrors参数设ؓ0Q表C只要遇C个错误更新就中止Q客L的日志保持不变。如果MaxErrors参数设ؓ-1Q当应用服务器发现有错误的记录,尝试更C一个记录,{所有的记录都尝试过以后才返回?br /> ApplyUpdates会自动调用Reconcile函数Q进而调用应用服务器上的TProvider构g的ApplyUpdates函数L新远E的数据库服务器。没有被DBMS服务器认可的记录通过Reconcileq回l客LQ此时将在客L触发OnReconcileError事g让?zhn)更正错误。最后,ApplyUpdates函数q回仍然没有被认可的记录数?br />11.7 在文件中存取数据
要从文g中读取数据,可以调用LoadFromFile函数。LoadFromFile函数需要传递一个参敎ͼ用于指定文g名。文件名应包含完整的路径。如果客L序L从一个固定的文g中读取数据,可以讄FileName属性指定一个文件名Q以后,当TClientDataSet引入的数据集打开Ӟp动从q个文g中读取数据,不需要调用LoadFromFile?br /> 要从中d数据Q可以调用LoadFromStream。LoadFromStream需要传递一个参敎ͼ用于指定一个流对象?br /> 注意QLoadFromFile(LoadFromStream)只能从先前用SaveToFile(SaveToStream)保存的文件中d数据?br /> 要把数据保存到文件中Q可以调用SaveToFile函数。SaveToFile需要传递一个参敎ͼ用于指定文g名。如果指定的文g已存在,文g中的数据被覆盖。如果客L序L把数据保存到一个固定的文g中,可以讄FileName属性指定一个文件名Q当TClientDataSet引入的数据集关闭Ӟp动把数据保存到这个文件中Q不需要调用SaveToFile?br /> 要把数据保存到流中,可以调用SaveToStream。SaveToStream需要传递一个参敎ͼ指定一个流对象?br /> 注意Q当把数据保存到文g或流中时Q日志中记蝲的修改仍然保留。这P当下ơ调用LoadFromFile或LoadFromStreamd数据Ӟ仍然可以恢复原来的数据?
]]>
一?/span>Midas的安全问题?/span>
Midas技术是Delphi中进行三层开发的首选技术,它不仅有U?/span>DCOM/COM+(COM+技术是.NET技术的基础)的优点,而且也结合了Delphi的快速开发特性,可以快速开发出惌的系l,其开发速度是用VC,PB{开?/span>DCOM的数十倍,把程序员从烦杂的代码中解脱出来,从而将更多的精力投入到业务逻辑的设计中厅R?/span>
但是Midas技术的一个最令h担忧的就是它的安全问题:
q端只要知道应用服务器的端口号即可访问到应用服务器,而一旦访问到应用服务器,TClientDataSet卛_获得ProviderNames列表。一旦知道了ProviderNames列表Q这q当于数据库暴露在外了?/span>
关于可轻易获?/span>ProviderNames列表的问题,我用下面的Ҏ(gu)解决Q?/span>
在服务器端定义一?/span>
LoginMTS(const AUserId, APassword: WideString): WordBool;
Ҏ(gu)。初始状态下Q所有的DataSetProvider和数据集的连接断开。用户必调?/span>LoginMTSq传递用户名和密码,登陆成功才将DataSetProvider和数据集的连接打开。这样如果用户验证没有通过Q即使它获得?/span>ProviderNames列表也没法调用接口中的方法对数据库进行操作?/span>
二?/span>Midas中主从表的实?/span>
M表的应用在信息系l中应用很广。在两层开发中我们可以通过直接建立两个数据集之间ؓM关系来实C从表Q在三层中虽然我们仍然可以通过直接建立两个数据集之间ؓM关系来实C从表Q但是这样就要求把数据库中所有相关的数据行都下蝲到本圎ͼ丧失了三层开发的优势。我在实际中使用下面的方法实现。这里我以实现入库单查询、添加、修攏V删?/span>(CRUD)Z来讲解:
Q?/span>1Q新Z?/span>MTS Data ModuleQ命名ؓTmtsStockInListBiz,增加如下Ҏ(gu)Q?/span>
function QueryStockInListMasterById(const AId: WideString;
var ADatas: OleVariant): WordBool; safecall;
function QueryStockInListSlaveByMasterId(const AId: WideString;
var ADatas: OleVariant): WordBool; safecall;
procedure UpdataStockInListMaster(var ADatas: OleVariant); safecall;
procedure UpdataStockInListSlave(var ADatas: OleVariant); safecall;
function GenerateStockInListId: WideString; safecall;
QueryStockInListMasterById作用是根据入库单单号查询入库单的基本信息Q入库日期、负责h{)Q?/span>Aid为入库单单号Q?/span>Adatas回|其格式就?/span>Midas的数据包Q可以将光l?/span>ClientDatSet?/span>Data属性?/span>
QueryStockInListSlaveByMasterId作用是根据入库单单号查询入库单的详细信息Q商品条码,数量Q?/span>
UpdataStockInListMaster是对入库单主表进行删除、添加、修Ҏ(gu)作。只要将ClientDataSet?/span>Delta属性做Z递即可?/span>
UpdataStockInListSlave是对入库单从表进行删除、添加、修Ҏ(gu)作?/span>
GenerateStockInListId是生一个唯一的入库单受?/span>
下面是几个方法的代码Q都很简单,׃多解释了Q可以查?/span>Delphi的帮助?/span>
function TmtsStockInListBiz.QueryStockInListMasterById(
const AId: WideString; var ADatas: OleVariant): WordBool;
begin
result := false;
ADatas := null;
try
cdsQuery.Close;
cdsQuery.CommandText := 'select * from t_StockInListMaster where Id=:Id';
cdsQuery.Params.ParamByName('Id').AsString := AId;
cdsQuery.Open;
if cdsQuery.RecordCount > 0 then
begin
result := true;
ADatas := cdsQuery.Data;
end;
finally
cdsQuery.Close;
end;
end;
procedure TmtsStockInListBiz.UpdataStockInListMaster(
var ADatas: OleVariant);
var
eCount: Integer;
OwnerData: OleVariant;
begin
DCOMConStockInList.GetServer.AS_ApplyUpdates('dspStockInListMaster',
ADatas, -1, eCount, OwnerData);
end;
function TmtsStockInListBiz.GenerateStockInListId: WideString;
var
LPrior: string;
i: Integer;
begin
cdsQuery.Close;
cdsQuery.CommandText := 'select top 1 id from t_StockInListMaster order by id desc';
cdsQuery.Open;
LPrior := cdsQuery.FieldByName('Id').AsString;
i := StrToIntDef(RightStr(LPrior,8),0);
Inc(i);
result := 'RK' + FormatFloat('00000000',i);
cdsQuery.Close;
end;
Q?/span>2Q、新Z个应用程序,通过DCOMConnection?/span>SocketConnection{连接到MTSlgQ然后就可以调用MTS的相应的Ҏ(gu)实现客户端功能了?/span>
攑օcdsStockInListMaster?/span>cdsStockInListSlave两个ClientDataSet控gQ在控g上点d键,选择?/span>FieldsEditor”新Z服务器中的字D同L字段Q然后再ơ在控g上单d键,选择?/span>CreateDataSet”,建立一个本地数据库?/span>
Q?/span>3Q?/span>
Ҏ(gu)入库单号查询入库单的Ҏ(gu)实现Q?/span>
procedure TFormStockInList.BtnFindClick(Sender: TObject);
var
v,vs: OleVariant;
begin
if SocketConStockInList.AppServer.QueryStockInListMasterById(Trim(LEdtId.Text), v) then
begin
cdsStockInListMaster.Data := v;//昄入库单主表(主要信息Q?/span>
if SocketConStockInList.AppServer.QueryStockInListSlaveByMasterId(Trim(LEdtId.Text), vs) then
cdsStockInListSlave.Data := vs; ;//昄入库单从表(明细信息Q?/span>
end
else
ShowMessage('此单不存在!');
end;
Q?/span>4Q新建入库单的实?/span>
procedure TFormStockInList.BtnNewClick(Sender: TObject);
var
LId: string;
begin
ClearCDSRecord;
cdsStockInListMaster.Open;
cdsStockInListMaster.Insert;
LId := SocketConStockInList.AppServer.GenerateStockInListId;
LEdtId.Text := LId;
cdsStockInListMaster.FieldByName('Id').AsString := LId;
cdsStockInListMaster.FieldByName('GenerateDate').AsDateTime := Now();
end;
Q?/span>5Q提交功能的实现
procedure TFormStockInList.BtnPostClick(Sender: TObject);
var
LQuerymts: ImtsQueryObjDisp;
LBar: string;
begin
SetSocketConnectionConnect(SocketConQuery);
LQuerymts := ImtsQueryObjDisp(SocketConQuery.GetServer);
SocketConQuery.Close;
if cdsStockInListMaster.RecordCount > 0 then
SocketConStockInList.AppServer.UpdataStockInListMaster(cdsStockInListMaster.Delta);
if cdsStockInListSlave.RecordCount > 0 then
SocketConStockInList.AppServer.UpdataStockInListSlave(cdsStockInListSlave.Delta);
end;
注:本文?/span>ClientDataSet控g的名U开头一般ؓcds?/span>TsocketConnection控g的名U开头一般ؓSocketCon?/span>
三、动态设|?/span>TsimpleObjectBroker的服务器列表
procedure SetSocketConnectionConnect(AValue: TSocketConnection);
procedure FillAppServerList(ABroker: TSimpleObjectBroker);
var
sl: TStringList;
i, n: Integer;
begin
sl := TStringList.Create;
从配|文件中d服务器列表,q保存到sl?/span>;
n := sl.Count - 1;
ABroker.ServerData := null;
for i := 0 to n do
begin
ABroker.Servers.Add;
ABroker.Servers[i].ComputerName := sl.Strings[i]
end;
sl.Free;
end;
var
LBroker: TSimpleObjectBroker;
begin
LBroker := TSimpleObjectBroker.Create(nil);
FillAppServerList(LBroker);
AValue.ObjectBroker := LBroker;
try
AValue.Connected := true;
except
raise Exception.Create('应用服务器连接错误!');
end;
LBroker.Free;
end;
7.如何截取韌Q?/strong>
14. 如何讄输出参数Q?/strong>
{:启动韌截取软gAudioGrabber,音乐CD攑օ光驱Q勾选想要截取的CD韌?
点击控制栏中的“Settings”按键后N其中的“ASPI”项Q其它选项用默认值即可。然后,q入“Norm”选项Q选择“Use normalizing”后点击“OK”退出。现在,先用鼠标点击一下工h里那标有伸开手掌的“截取”(GrabQ钮,可以开始抓取指定的韌了。如果截L.WAV文g不能被正常读取或?WAV文g中有令h讨厌的“爆音”(popsQ这是o许多朋友头痛的问题)。请在“开始—设|—控刉李쀔系l—设备管理—CDROM—属性—设|—选项”中“同步数据传送”选中Q然后按“确定”退出。再重新去试截取刚才有问题的韌Q?zhn)可能会发玎ͼ问题已经q刃而解了。其ơ,若觉得光p取音乐数据的速度很缓慢,请先查光׃数据U是否直接接CL的IDE接口上?
Z方便理和用,可新建Photo、Audio、Wav三个子目录,分别用于存放照片、音乐及旁白?
准备工作完成后,可以开始着手制作了。ؓ了工作得更有条理Q我们一般先Ҏ(gu)一个相对独立的片段q行~辑制作Q最后再把它们连成整体?
8.如何讄才能让Premier5.0利用MPEGator来进行高效硬件压~?
{:首先启动Premiere5.0。在弹出的New Project settingH口Q选择General settings,在“编辑模式”里选“Video for window”,其下的两个选项均选?5”(因ؓ我们要制作的是PAL制式的VCD)Q然后进Video settings,在“压~器QCompressorQ”这一中选“DVMPEG Video (hardware)??8)Q即选用g压羃Q分辨率设ؓ352*288Q率设?5Q在Audio settings里,关键是在“Type(cdQ”中选择“DVMPEG Audio?--指定用硬件进行音频压~;采样频率设ؓ44.1KHZQ格式设?6bit--Stereo?
9.Premiere 5.0的主界面的结构如何?
{:q入Premiere 5.0的主界面Q我们会发现设计新颖的时间uH口(Timeline)已取代了?.2版本中的ConstractionH口。作为Premiere 5.0的核心,Timeline的用L口分Z个部份:视频部分和音频部分;其中视频部䆾又分Z个主视频剪辑轨道——Video 2和Video 1。其中,标成黑体字的Video 1部䆾又内含两个视频剪辑轨道:Video 1A和Video 1BQ它们之间的Transition轨道是视频切换效果轨道。Premiere 5.0提供了非怸富的视频切换效果Q包括滑动、擦除、融合、剥落、分剌Ӏ爆破、渐变、突变、三l旋转、翻c推动等多种划变效果Qo人目不暇接。音频轨道Audio 1??则用于放|背景音乐、配韟뀁旁白等声音信号。
10.如何导入囄及配xӞ
{:点击“File--Import--Folder”,把刚才准备好的图片文件及背景音乐文g输入q来Q在ProjectH口下双d才输入的文g夹,可以看到文g夹中的各文g的具体信息,双击该文件则可对其进行预览。
11.如何讄照片的参敎ͼ
{:第一q照片拖到视频剪辑轨道Video 1A中,对其点击鼠标右键Q在弹出的菜单中的Durationw讑֮照片的播放时_q在菜单中的VideowMaintain Aspect Retio选中(?9)——请注意Q这是非帔R要的一步,此项讄最后输出的照片保持原本的长宽比例,而不致于使照片上的h像、景物发生变形。按上述Ҏ(gu)照片依ơ拖入Video1的A、B栏,(注意每幅照片的尾与下一q照片首应留有重叠部份,重叠部䆾的时间长短依实际需要而定。把背景音乐、旁白拖入Audio栏)。如果是旁白Q应特别注意旁白的时间长度应与相应照片的播放旉相当。然后,用鼠标把TimelineH户上方的浅蓝色横杠拉至最后一张照片的末端Q以讑֮Premiere进行处理的视频片段的长度?
12. 如何讑֮视频切换Ҏ(gu)Q?/strong>
{:Premiere 5.0用户界面?有一个TransitionQCommand命oH口Q其中共?5U切换特效可供选择。而且Q其中大多数切换Ҏ(gu)都可按自q需要进行设|。将选中的特效用鼠标拖到Video 1H口的Transition中两q照片相重叠的部分,光度应Zq照片相重叠的长度。如果能Ҏ(gu)每幅照片的特Ҏ(gu)当地选择TransitionsQ将使?zhn)的VCD相册在播放时赢得更多的赞叹之声。
13. 如何处理背景音乐Q?/strong>
{:为VCD相册d优美的背景音乐,也将使你的VCD相册qx许多qh的魅力。然而,因ؓ背景音乐是我们采用抓韌的方式获得的Q这样就不可避免地在VCD相册一开始播放时出现突兀而至的音乐声。此外,׃韌的长度与照片播放旉的长度往往难以很好的吻合。这P可能出CDVCD相册的播N上就要结束,而音乐声却正处于高潮……。理想的状况应该是:照片播放Ӟ背景音乐逐渐L地响P照片播放卛_l束Ӟ音乐声又渐渐随之淡去。换句话_也就是要实现背景音乐的E入E出。在Premiere 5.0中,按前q方法装入照片及背景音乐后,单击W一音频轨道QAudio 1Q上的那个指向右的小三角Q这时会弹出该音轨的波Ş昄框。可以看到该框中部有一条左叛_有一方Ş端点的红U쀔—这是控制音乐淡入淡出的关键。将鼠标U至U线上,鼠标指针变为手??0)。此Ӟ按住鼠标左键卛_通过增加和拖动点子来随意定该红U条形状。从起始位置开始,线条置于从左至x高状态时Q即可实现背景音乐的淡入效果。用cM的方法还可制造音乐的淡出效果Q在此不再赘q。有兴趣的朋友尽可自行尝试。?/p>
{:输出参数包含General、Audio、Video三项Q只有正的讑֤了输出参敎ͼVCD相册才能在VCDZ利播放。首先选Project--Settingq入General讄Q在“Editing Mode”里选“Video for window”,“Time display”及“Timebase”均选?5”;再进入Video讄Q“Compressor”选“DVMPEG Video(Hardware)”,寸设ؓ352*288Q率设?5Q最后设|Audio参数Q采样频率设?4.1KHZQ格式设?6bit--Stereo(?1)QType设成“DVMPEG Audio”。在q里Q音频及视频均设|ؓgQMPEGator卡)加速压~。?br />
15. 如何直接输出MPG文gQ?/strong>
{:上述参数讄完毕后,接着选File-Export-movieQ将刚才l合好的照片Q音乐,旁白{素材,通过MPEGator卡的g加速直接生成高质量的MPG文g。我们知道,如果利用Xing MPEG Encoder{进行纯软g压羃Q即使你的系l配|较高,其压~时间也O长得惊hQ约为真实播放时间的10-20倍;而利用MPEGator卡进行硬件压~的话,可就太节省时间了Q压~时间仅为真实播放时间的3倍左叻I大大提高了制作效率。需要注意的是,Z便于分类Q应把同一主题的内容输出生成一个独立的MPG文g?
16. 如何把电(sh)子相册刻成VCD?
前面所有辛苦的力_Q都通过d成VCD片而变成劳动的果实。说?.0 VCDdQCeQuadrat出品的Video Pack 4.0因其较细致而周到的功能设计Q是一个在业余条g下不错的选择Q其~点是操作相Ҏ(gu)较繁琐。启动Video Pack 4.0Q将刚才压羃好的各个MPG文g依次用鼠标拖至位于主界面下方的工作框内,右键单击MPG文gQ在弹出的菜单选中PropertiesQ在Playlist node中的W二个选项Q即每一片段的等待时_里把{待旉设ؓ0U,按“确定”退出。每个MPG文g都必重复上q步骤,q样可以使各独立主题内容切换时不至于出现停顿{待状态。这时你也许发现了,刚才拖入工作框的各MPG文g方Ş图标上下均有一个三角Ş~口。原来,在Video Pack 4.0中是用连U的方式来表C各U播放次序的Q而这U三角Ş~口Q就是这些连U的出入口。将鼠标指针U至MPG文g图标下方的缺口,图标里会出现黄颜色的“Next”字P此时卛_开始进行连U,Ҏ(gu)是各MPG文g按顺序首q??2)。上q步骤完成后Q点dh中的U色的“Make CD”钮卛_开始刻录VCD光碟了?
17. 把电(sh)子相册刻成VCD的q程中要注意哪些事项Q?/strong>
要是现在问你Q自己刻制一张VCD相册光盘困难吗?你肯定会_一炚w不难Q?
那么Q是不是像在硬盘上拯文g那么轻而易丑֑Q决非如此简单。VCD相册d前进行些必要的准备工作,能大大提高我们的刻录成功率Q
a.d前ؓ什么要整理盘Q?
{:我们通常都是以硬盘作Z息源盘来q行d的。由于未l整理的盘文g大多呈零散状态分布。这P盘在读取数据时Q读写头只能在零散的文件之间来回奔忙,极有可能造成不必要的延误而导致刻出废盘。所以,每次d前对盘的每一个逻辑分区q行盘扫描和碎片整理。进行硬盘整理是成功d的第一步。
b.Z么刻录过E中要避免执行Q何无关程序?
{:q些E序不仅包括屏幕保护E序和内存驻留程序(比如某些杀毒程序)Q这些程序都有可能在数据从盘转移到刻录机中光盘上的紧要关_来与d软g争夺有限的系l资源,从而媄响数据流的正怼输而引发缓存器Ơ蝲{问题,Dȝp|?
c.Z么用质量可靠的CD-R盘片Q?
{:CD-RI白盘片按反层材料的不同可分绿盘、金盘、蓝盘三大类。这三种盘片q没有明昄优劣差别。从Ҏ(gu)上来说Q绿盘具有较好的兼容性,另外h很便宜;蓝盘在写入和d数据时有较高的准性;金盘有较好的抗光性。关键的是,分别试刻不同cd和品牌的盘片Q从中找出最适合你的d机的那几U。
xQ两U不同类型的?sh)子相册的制作方法就介绍完毕Q预你早日制作q_?sh)子相册Q?/p>
]]>
如图 1 ?/span> Hibernate 设计?/span> CriteriaSpecification 作ؓ Criteria 的顶U接口,其下面提供了 Criteria ?/span> DetachedCriteria ?/span>
Criteria ?/span> DetachedCriteria 的主要区别在于创建的形式不一P Criteria 是在U的Q所以它是由 Hibernate Session q行创徏的;?/span> DetachedCriteria 是离U的Q创建时无需 Session Q?/span> DetachedCriteria 提供?/span> 4 个静态方?/span> forClass(Class) ?/span> forEntityName(Name) q行 DetachedCriteria 实例的创建?/span> Spring 的框架提供了
getHibernateTemplate().findByCriteria(detachedCriteria) Ҏ(gu)可以很方便地Ҏ(gu)
DetachedCriteria 来返回查询结果?/span>
如图 1 Q?/span> Criteria ?/span> DetachedCriteria 均可使用 Criterion ?/span> Projection 讄查询条g。可以设|?/span> FetchMode( 联合查询抓取的模?/span> ) Q设|排序方式。对?/span> Criteria q可以设|?/span> FlushModel Q冲?/span> Session 的方式)?/span> LockMode Q数据库锁模式)?/span>
下面对 Criterion ?/span> Projection q行详细说明?/span>
?/span> 1
Criterion ?/span> Criteria 的查询条件?/span>
Criteria 提供?/span> add(Criterion criterion) Ҏ(gu)来添加查询条件。图 2 ?/span> Criterion 的结构图?/span> Criterion 接口的主要实现包括: Example ?/span> Junction ?/span> SimpleExpression 。?/span> Junction 的实际用是它的两个子类 conjunction ?/span> disjunction Q分别是使用 AND ?/span> OR 操作W进行来联结查询条g集合?/span>
Criterion 的实例可以通过 Restrictions 工具cL创徏Q?/span> Restrictions 提供了大量的静态方法,?/span> eq Q等于)?/span> ge Q大于等于)?/span> between {来Ҏ(gu)的创?/span> Criterion 查询条g
Q?/span> SimpleExpression 实例Q。除此之外, Restrictions q提供了Ҏ(gu)来创?/span> conjunction ?/span> disjunction 实例Q通过往该实例的 add(Criteria) Ҏ(gu)来增加查询条件Ş成一个查询条仉合?/span>
至于 Example 的创建有所不同Q?/span> Example 本n提供了一个静态方?/span> create(Object entity) Q即Ҏ(gu)一个对象(实际使用中一般是映射到数据库的对象)来创建。然后可以设|一些过滤条Ӟ
Example exampleUser =Example.create(u)
.ignoreCase() // 忽略大小?/span>
.enableLike(MatchMode.ANYWHERE);
// ?/span> String cd的属性,无论在那里值在那里都匹配。相当于 %value%
?/span>
2
Project 主要是让 Criteria 能够q行报表查询Qƈ可以实现分组?/span> Project 主要?/span> SimpleProjection ?/span> ProjectionList ?/span> Property 三个实现。其?/span> SimpleProjection ?/span> ProjectionList 的实例化是由内徏?/span> Projections 来完成,如提供的 avg ?/span> count ?/span> max ?/span> min ?/span> sum 可以让开发者很Ҏ(gu)Ҏ(gu)个字D进行统计查询?/span>
Property 是对某个字段q行查询条g的设|,如通过
Porperty.forName(“color?.in(new String[]{“black?”red?”write”}); 则可以创Z?/span> Project 实例。通过 criteria ?/span> add(Project) Ҏ(gu)加入到查询条件中厅R?/span>
?/span>
3
使用 Criteria q行查询Q主要要清晰的是 Hibernate 提供了那些类和方法来满开发中查询条g的创建和l装Q其l构层次如何。这样用v来便可得心应手?/span>