delphi2007 教程

delphi2007 教程

首页 新随笔 联系 聚合 管理
  1013 Posts :: 0 Stories :: 28 Comments :: 0 Trackbacks

2009年7月15日 #

声明:本文乃 熊恒(beta) 原创,如要转载请保持文章完整。 深入研究 case 语句 --- by 熊恒(beta) 不小心在论坛上引发舌战,当中涉及到了 if then else if 的连续使用和直接使 用 case 的情况下,效率孰高孰低的问题。今天的话题就从解决这个争论开始吧, 在最前面,我不想多说什么,实践是检验真理的唯一标准,咱们用例子说话: // 例一 procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin i := 7; if i = 0 then ShowMessage('0') else if i = 1 then ShowMessage('1') else if i = 5 then ShowMessage('5') else if i = 10 then ShowMessage('10') else if i = 7 then ShowMessage('7') else if i = 9 then ShowMessage('9') else ShowMessage('X'); end; // 例二 procedure TForm1.Button2Click(Sender: TObject); var i: Integer; begin i := 7; case i of 0: ShowMessage('0'); 1: ShowMessage('1'); 5: ShowMessage('5'); 10: ShowMessage('10'); 7: ShowMessage('7'); 9: ShowMessage('9'); else ShowMessage('X'); end; end; 咱们先从例一开始(把精彩的留在后面:-p)。这是典型的 if then else if 使 用,看一下它对应的汇编代码: i := 7; mov eax, $00000007 if i = 0 then test eax, eax // 可以看到编译器很聪明的,和 0 的比较被优化了 jnz +$0b // 若不为 0 则跳转到下一个 if ShowMessage('0') ... // 省略不必要的部分 else if i = 1 then cmp eax, $01 jnz +$0c // 若不为 1 则跳转到下一个 if ShowMessage('1') ... else if i = 5 then cmp eax, $05 jnz +$0c // 若不为 5 则跳转到下一个 if ... // 后面部分不必再看了 可以看到它是一个 if 一个 if 地“规规矩矩”地进行顺序比较的,要是你一共 有 1M 个可能性,并且刚好所有的 if 都不成立(没有找到对应选项),那就要 轮到最后一个 else,可想而知,要进行多少次痛苦的比较。 再看一看例二,采用的是 case 语句,还是先看汇编代码: i := 7; mov eax, $00000007 case i of cmp eax, $0a jnbe +$75 jmp dword ptr [eax * 4 + $0045239d] ... // 后面虽然还有但是由于上面这个 jmp,就不用看了 这最后三句汇编代码非常值得我们仔细推敲!其实 case i of 从决策到跳转一共 只用了三条汇编代码!优美! 先看第一句:cmp eax, $0a 从前面一句可以看到,eax 里面就是我们的 i 的值,那么把它和 $0a 相比 又是什么意思呢?$0a 的十进制值就是 10,看看前面的代码,的确有 10 这个选 项。why 10? 这肯定是首先浮现在你脑子里的问题,如果你仔细看,会发现,10 是几个选项里面最大的一个。(这正是我为什么把 10 这个最大的选项排在中间, 而不是最后,就是为了说明这个 $0a 是指的所有选项的最大值,而不是最后一个 选项的值!) 第二句:jnbe +$75 很好理解,如果 i 大于所有选项中最大的(即找肯定不到对应选项),则直 接跳转到 else 部分。回想前面的例一,要是出现找不到的情况,将是人生(不, 应该说是 CPU 的)一大悲哀 :-) 好了,前面已经排除“异己”了,现在来看它是如何找到“党组织”的。 第三句:jmp dword ptr [eax * 4 + $0045239d] 跳转了。跳到哪里了?以从 eax * 4 + $0045239d 单元里面取出的值作为跳 转的目的。有汇编基础的朋友应该可以看出,$004523f 是一个基地址,eax,我们 的 i,是可变的,也就是说这是一个查表的过程!类似于数组的使用 arr[i]。那 它查出来那么这个神秘的跳转目的地到底在哪里呢?一个单步(Step Over)就看 见光标停留在了 ShowMessage('7') 的位置。啊?就,找到组织了? 看一下它是怎么找到目的的。首先,把 i 作为一个索引,用查表的方式找出一 个数,然后它就说这个数就是我们梦寐以求的入口地址,直接跳过去了(晕~, 欲知详情,往下看)。因此,不管 i 在所有选项中处于什么位置,总是可以通过 这样的一个简单的查表,得到目的地址,只用一条跳转语句就过去了。 因此得出今天的结论:case 语句的效率高!依据是,if then else if 的平均时 间复杂度是 O(n/2),而 case 的时间复杂度是 O(1)。 当然了,如果本文就这样完了,那我肯定被读者的鸡蛋爆头——谜团尚未解开。 别急嘛,下面接着来: 首先当然是为什么能够通过一个简单的查表找到目的地址。我是这样理解的: Delphi 在编译的时候就建立了一个地址表。把所有选项的入口地址存入这个表中 (既然存的是地址,DWord 类型的,所以前面的第三句汇编代码里面有一个乘以 4 的动作)。这个表结构大致是这样的,第 0 项中放的是值为 0 的选项的入口 地址;第 1 项中放的是值为 1 的选项的入口地址。因此,只要有了这个表的基 地址(显然,这可以在编译时确定),事情就变得容易了。 假设 i 等于 7,于是我只要到那个表里面找出第 7 项的值,那自然就是值为 7 的选项的入口地址。呵呵,原来就这么简单。 现在你明白了为什么 case 语句只能用于顺序类型了吧(要不然怎么根据值建 这个表),它不是不能实现对其他类型的使用,而是不愿意,因为这样我们可以 获得极高的效率。我可不想看见 case 语句变成简单的 if then else if 的封装。 其实问题并没有解决完,回头看看刚才的那三行汇编代码的前两行,那仅仅是 排除了 i 大于最大选项值的情况。但是要是 i 为 6 呢?这是它虽然小于最大选 项值 10,但是它仍然不存在于选项表中。那,程序就顺序执行咯,照样根据 i 取出偏移索引值。那这个索引值会指引它跳向何处呢?当然是 else 部分的入口 地址咯(如果有 else 的话,如果没有,则跳出 case 到后面紧接着的代码行呗)。 那但是前面建表的时候,没有 6 这个选项,在表中第 6 项应该没有相应的值啊。 呵呵,这好办,把表里面那些没有对应选项值的“空位”全部填上 else 部分的入 口地址偏移值(若没有 else 部分则填 case 后面紧接着的代码行的地址)就可以 啦。好办法! 还有问题,要是选项里面有负数怎么办?怎么建表?容易,直接以最小的选项 值为基础,所有选项值减去这个负数,于是,选项值又从 0 开始了(当然,查表 的时候 i 也做相应变化)。那要是 i 是负数呢?仔细看那三句汇编的第二句: jnbe +$7c,jnbe 是判断无符号的,i 要是负数,把它看成无符号数,最高位就 是 1,自然大于所有的有符号正数(最高位为 0),而被当成异己,直接排除了。 最后一个问题,这个神秘的表到底建在什么地方呢?如果我的眼神没有退化的 话,它应该紧接着 case i of 即那三行汇编的后面。表后面就是所有选项的入口。 不过,在最大项和最小项之间的差值大于等于 15 的时候,查找地址的动作略有 不同,这应该和表所占空间有关系吧(这种情况没有深入研究,头有点晕了:-p)。 悄悄告诉你,当选项数目很少(小于 5)的时候,不会建立这个表,而是以另 外一种比较有趣的方法实现,你若有兴趣可以自己去看一下。还有,当最小选项 值大于 3 的时候,Delphi 会自动把所有选项的值减去该最小项的值,使最小项 从 0 开始,这样可以节约入口地址表的空间(当然,在用 i 来查表的时候,也 要先减去该值,否则就不对了)。 不管是谁,想到这个办法来实现多分支结构,同时能够极大地提高效率,的确是 个了不起的人。这也进一步让我认识到,编程的确是一项艺术。 差不多应该讲完了(我所知道的),就是不知道讲清楚没有,有问题大家一起探 讨吧。 原文:http://www.delphibbs.com/delphibbs/dispq.asp?lid=1406114

继续阅读《beta 的第三篇心得:深入研究 case 语句》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(305) | 评论 (0)编辑 收藏

声明:本文乃 熊恒(beta) 原创,如要转载请保持文章完整。 在 case 语句中使用字符串 --- by 熊恒(beta) 我今天要介绍的是一个比较另类的方法。大家都知道,case 语句只能对顺序类型 (ordinal type)管用,那么我们先看一下顺序类型到底有那些呢:1)整型;2)字 符型;3)枚举型。 于是也就演化出三种在 case 语句里面使用字符串的方法(耐心看下去哦,最后一 种方法才是今天的重点:-p): 假如我们的具体应用如下(理想的,但是错误的写法): str := 'Chongqing'; case str of // 编译器将在这一行制止你 :-( 'Beijing': ShowMessage('First'); 'Tianjing': ShowMessage('Second'); 'Shanghai': ShowMessage('Third'); 'Chongqing': ShowMessage('Forth'); else ShowMessage('Other'); end; 法一:字符串转为整型 这应该是比较通行的方法了,主要是利用 TStringList。先把备选的字符串挨个 Add 进去,然后调用其 IndexOf 方法。该方法返回一个整数,表示待找字符串出 现在列表中的位置: //var strList: TStringList; strList := TStringList.Create; strList.Add('Beijing'); strList.Add('Tianjing'); strList.Add('Shanghai'); strList.Add('Chongqing'); str := 'Chongqing'; case strList.IndexOf(str) of 0: ShowMessage('First'); 1: ShowMessage('Second'); 2: ShowMessage('Third'); 3: ShowMessage('Forth'); else ShowMessage('Other'); end; strList.Free; 可以看到,这是比较麻烦的方法了,不过你可得记住这个方法,因为后面的讨论 将会讲到,这是最通用的方法。 另:当然,把字符串转化为整型后用于 case 不只这一种方法。另一种是通过把 备选项全部转化为等长度后合并为一个字符串,然后用 Pos 函数返回某字符串的 位置。在此不再累述,请查阅《程序员》杂志(具体哪一期不记得了:-()。 法二:字符串转为字符型 这应该是最简单的一种方法,不过局限性比较大。如果你的备选项的第 N 个字 符(N 应为常数)都互不相同,那么你赚到了。这样,就可以通过取出这个字符, 来唯一标识你的字符串: str := 'Chongqing'; case str[1] of // 第一个字符都不同,所以取出第一个进行比较 'B': ShowMessage('First'); 'T': ShowMessage('Second'); 'S': ShowMessage('Third'); 'C': ShowMessage('Forth'); else ShowMessage('Other'); end; 不过如果你的备选项没有这样的特性,那么你就无缘使用这种方法了。 法三:字符串转为枚举型 这种方法主要用到 RTTI 的特性。该方法的主要思路是,先把所有的备选项声名 为一个枚举类型的值,那么我们只要把要找的字符串也转换为枚举型,那么就可以 用 case 语句了。那么通过什么办法把一个字符串转化为枚举型呢?往下看: // uses TypInfo; // 记得引用这个单元 // type TMyStrSel = (Beijing, Tianjing, Shanghai, Chongqing); // 注意,上面这个定义不能放在某个函数内部哦,那样的话,它就没有运行类信息了 // var strSel: TMyStrSel; str := 'Chongqing'; strSel := TMyStrSel(GetEnumValue(TypeInfo(TMyStrSel), str)); case strSel of Beijing: ShowMessage('First'); Tianjing: ShowMessage('Second'); Shanghai: ShowMessage('Third'); Chongqing: ShowMessage('Forth'); else ShowMessage('Other'); end; 稍做解释:GetEnumValue 函数返回一个字符串对应的枚举型的值在某枚举类型 中的位置(要知道枚举类型是有顺序的,要不怎么叫顺序类型呢:-)),然后通过 一个强制类型转换将这个值转化为枚举型。于是就实现了把字符串转化为枚举型的 操作。 可以看到,在 case 语句这一段,我们的使用和理想中的使用方法几乎是一样的! 毕竟枚举类型可以做到见名知意嘛。的确比用前两种方法看起来直观得多。 当然,这并不是万能的方法,如果你的备选项有一个不符合 Delphi 的变量名命 名法则(如'AK-47'或中文等),则不能将其声明为一个枚举型,于是就不能使用这 个方法。如果是这样你就只能使用前两种方法了。极端的情况下,至少你还有第一 种方法可以使用 :-) 但在不少的场合,这种方法还是适用的。 原文:http://www.delphibbs.com/delphibbs/dispq.asp?lid=1358621

继续阅读《beta 的第二篇心得:在 case 语句中使用字符串》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(237) | 评论 (0)编辑 收藏

声明:本文乃 熊恒(beta) 原创,如要转载请保持文章完整。 按名字调用方法高级解决方案 --- by 熊恒(beta) 按名字调用方法似乎一直以来都是大家比较关注的技术,在论坛上有一个经典的答复: type TProcedure = procedure(Test: string) of object; procedure ExecuteRoutine(Obj: TObject; Name, Param: string); var PMethod: TMethod; AProcedure: TProcedure; begin PMethod.Data := Pointer(Obj); PMethod.Code := Obj.MethodAddress(Name); if Assigned(PMethod.Code) then begin AProcedure := TProcedure(PMethod); AProcedure(Param); end; end; 使用:待调用方法声明为某个类的 published 方法,Obj 为拥有待调用方法的类的 实例,Name 和 Param 分别为待调用方法的名字和参数。 但是这个办法有一个很大的局限性:一旦 TProcedure 声明定了下来,待调用方法的参 数表也就一定了。要是我定义了多个待调用方法,且参数个数、类型、返回值均不同, 则这个办法也就无能为力了。另:用 GetProcAddress 代替 MethodAddress 也可以实 现类似的效果,不过我们今天讨论的是调用类的“方法”,而它所返回的不是“方法”, 因为 GetProcAddress 仅能取得应用程序的输出(exports)了的过程或函数,这些过 程或函数不属于任何类,也就称不上“方法”。当然,效果类似,但是局限也类似 :-( 那么要是参数的个数、类型均可变就无法解决了吗?(要是这样就不会有本文了)通过 研究,我发现了一种行之有效的办法:Format 函数(注意,不是 DOS 命令,呵呵)相 信大家都不陌生吧,传入它的参数的个数和类型不都是可变的吗?只要声明如下: procedure AProc(Param: array of const); 即可这样调用: AProc([123, 'X', True, 'hello'...]); 有朋友可能要说了,那不就简单了,这样不就可以了: type TProcedure = procedure(Params: array of const) of object; procedure ExecuteRoutine(Obj: TObject; Name: string; Params: array of const); var ... begin ... AProcedure(Params); ... end; 别急,问题才刚刚出现呢,你运行试一试?出问题了吧。(为方便起见,暂时称我们的 ExecuteRoutine 函数,为控制函数;待调用方法简称为待调方法)这个形参表的声明 办法的确适合我们的控制函数,但是不适合待调方法。为什么?因为待调方法的形参表 的确不是这样(array of const)的啊。当然了,你说你把所有待调方法的形参表都改 成这个样子不就可以了?且不说你需要改动多少东西(包括待调函数的参数表和内部实 现,关键是内部实现部分),就看看你改了过后的待调方法的形参表,全部都成了一个 模样。说不定到时候你自己都不知道到底应该传什么参数进去了。因此,我们应该尽量 保持待调方法的形参表。 现在问题转化为了在控制函数中已知待调方法的地址及其参数列表(存放在一个 TVarRec 的数组中),如何在调用它的时候将参数传进去。这需要几点预备知识: 1. 首先我们来看看传进来的这个参数表:Params。它的类型被 Delphi 称作可变开 放数组(Variant open array),等价于 array of TVarRec,也就是说 Params 是一 个成员为 TVarRec 的数组。换句话说,在参数被传进 Params 的时候,各种类型都被 Delphi 自动转化为了 TVarRec(参见帮助中的 Variant open array parameters 一 节)。看一下 TVarRec 的定义可知,它实际储存的数据域为 4 Bytes,超过 4 Bytes 的只存指针,需要注意的是 TVarRec 的大小是 8 Bytes(经研究发现前 4 Bytes 存放 数据,第 5 Byte 为类型)。 2. 调用函数时的参数传递的一般情况(未使用 stdcall 的情况)。对于一般的函数 或过程,前三个参数分别放在 EAX、EDX、ECX,后面如果还有更多参数的话,就在堆栈 里面;对于类的方法,EAX 固定用于存放类实例的地址,EDX、ECX 分别存放前两个参 数,其余参数进栈。在堆栈中每个元素占用 4 Bytes,而前面说了,TVarRec 中储存的 数据也是 4 Bytes,刚好一个参数在堆栈里面占一个位子,处理方便。另外,结果返回 到 EAX 中。 3. 对于调用类的方法,其实有一个默认的隐藏参数 Self 作为第一个参数传入,放 入 EAX 寄存器。因此我们看到的第一参数其实是第二个,因此我们处理的时候要注意。 4. 用 ObjectPascal 语法调用方法,Delphi 会自动帮我们处理参数的传递问题,而 在汇编里面调用任何函数之前都需要先手动设置各参数。 因此,我决定用内嵌汇编的办法来解决参数传递问题:如果是一个参数,放入 EDX;若 为两个参数,分别放入 EDX,ECX;对多于两个参数的情况,用 参数个数 - 2 个循环依 次将后续参数进栈。然后将拥有待调方法的实例地址传入 EAX,就可以 CALL 了。 function ExecuteRoutine(AObj: TObject; AName: string; Params: array of const): DWord; const RecSize = SizeOf(TVarRec); // 循环处理参数列表时递增的字节数 var PFunc: Pointer; ParCount: DWord; begin if not Assigned(AObj) then raise Exception.Create ('你确定传进来的是一个对象?'); PFunc := AObj.MethodAddress(AName); // 获取方法地址 if not Assigned(PFunc) then raise Exception.CreateFmt('找不到 %s 的 Method: %s', [AObj.ClassName, AName]); ParCount := High(Params) + 1; // 获取参数个数 asm PUSH ESI // 保存 ESI,我们待会儿要用到它 MOV ESI, Params // ESI 指向参数表首址 CMP ParCount, 1 // 判断参数个数 JB @NoParam JE @OneParam CMP ParCount, 2 JE @TwoParams @ManyParams: // 超过两个参数 CLD // 清空方向标志 MOV ECX, ParCount SUB ECX, 2 // 循环 ParCount - 2 次 MOV EDX, RecSize // EDX 依次指向每个参数的首址,每次递增 8 Bytes ADD EDX, RecSize // 跳过前两个参数 @ParamLoop: MOV EAX, [ESI][EDX] // 用基址变址寻址方式取得一个参数 PUSH EAX // 参数进栈 ADD EDX, RecSize // EDX 指向下一个参数首址 LOOP @ParamLoop @TwoParams: // 两个参数 MOV ECX, [ESI] + RecSize @OneParam: // 一个参数 MOV EDX, [ESI] @NoParam: MOV EAX, AObj // 传入实例地址(即,隐藏参数 Self) CALL PFunc // 调用方法 MOV Result, EAX // 返回值放入 Result POP ESI // 记得还原 end; end; 前面已经说过了,任何类型都可以塞进 4 Bytes,因此将返回值定义为 DWord,你可以 根据自己的需要进行类型转换。这个办法最大限度地保护了待调方法,但也不是完全不 用修改,只有一个地方需要作出适当调整:与 DLL 中的函数返回值一样(别告诉我引用 ShareMem,那不属于本文讨论的范畴),如果要返回一个长 string,请改为 PChar, 并注意申请必要的空间。 以下是一个使用的例子(再次提醒一下,待调方法必须是某个类的 published 方法): TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } published // 几个待调方法 function TowInt(I, J: Integer): Integer; function ThreeInt(I, J, K: Integer): Integer; function FiveInt(X1, X2, X3, X4, X5: Integer): Integer; function ThreeChar(I, J, K: Char): PChar; function TwoStr(X, Y: string): PChar; function IntNBool(I: Integer; B: Boolean): Boolean; end; ... function ExecuteRoutine(AObj: TObject; AName: string; Params: array of const): DWord; ... function TForm1.TowInt(I, J: Integer): Integer; begin ShowMessage(Format('%d + %d', [I, J])); Result := I + J; end; function TForm1.ThreeInt(I, J, K: Integer): Integer; begin ShowMessage(Format('%d + %d + %d', [I, J, K])); Result := I + J + K; end; function TForm1.FiveInt(X1, X2, X3, X4, X5: Integer): Integer; begin ShowMessage(Format('%d + %d + %d + %d + %d', [X1, X2, X3, X4, X5])); Result := X1 + X2 + X3 + X4 + X5; end; function TForm1.ThreeChar(I, J, K: Char): PChar; var Res: string; begin ShowMessage(Format('%s + %s + %s', [I, J, K])); Res := I + J + K; Result := AllocMem(Length(Res) + 1); StrPCopy(Result, Res); end; function TForm1.TwoStr(X, Y: string): PChar; var Res: string; begin ShowMessage(Format('%s + %s', [X, Y])); Res := X + Y; Result := AllocMem(Length(Res) + 1); StrPCopy(Result, Res); end; function TForm1.IntNBool(I: Integer; B: Boolean): Boolean; begin if B then ShowMessage(IntToStr(I) + ' and True') else ShowMessage(IntToStr(I) + ' and False'); Result := B; end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; b: Boolean; s: string; begin i := ExecuteRoutine(Self, 'ThreeInt', [10, 23, 17]); ShowMessage('Result: ' + IntToStr(i)); i := ExecuteRoutine(Self, 'FiveInt', [1, 2, 3, 4, 5]); ShowMessage('Result: ' + IntToStr(i)); b := Boolean(ExecuteRoutine(Self, 'IntNBool', [10, False])); if b then ShowMessage('Result: True') else ShowMessage('Result: False'); s := PChar(ExecuteRoutine(Self, 'ThreeChar', ['a', 'b', 'c'])); ShowMessage('Result: ' + s); s := PChar(ExecuteRoutine(Self, 'TwoStr', ['hello', ' world'])); ShowMessage('Result: ' + s); end; ... 我之所以称该办法为高级解决方案,而非终极,因为它仍然有一个问题没有解决:变参 问题。但是这不是什么大问题,因为完全可以用函数返回值代替变参。啊?你要返回多 个值?那建议返回一个指向结构体的指针,或一个最简单的对象。 原文:http://www.delphibbs.com/delphibbs/dispq.asp?lid=1289838

继续阅读《beta 的第一篇心得:按名字调用方法高级解决方案》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(211) | 评论 (0)编辑 收藏

e100 33 f6 bf 0 20 b5 10 f3 a5 8c c8 5 0 2 50 68 13 1 cb e 1f be a1 1 bf 0 1 e11b 6 57 b8 11 1 bb 21 13 89 7 4b 4b 48 79 f9 ad 86 e0 8b c8 bd ff ff e8 20 e134 0 3d 0 1 74 1a 7f 3 aa eb f3 2d ff 0 50 e8 f 0 5a f7 d8 8b d8 26 8a 1 aa e14f 4a 75 f9 eb de cb 57 bb 21 13 8b c1 40 f7 27 f7 f5 8b fb ba 11 1 4f 4f 4a e168 39 5 7f f9 52 8b c5 f7 25 f7 37 2b c8 95 f7 65 2 f7 37 95 2b e8 fe e fe e181 10 79 6 c6 6 fe 10 7 46 d0 14 d1 d1 d1 e5 79 ec 5a b8 11 1 ff 7 4b 4b 48 e19b 3b d0 75 f7 5f c3 83 f7 83 a6 5d 59 82 cd b2 8 42 46 9 57 a9 c5 ca aa 1b e1b4 4f 52 b4 92 3f ab 6e 9e a8 1d c6 3 fc e 6a e7 ae bb 5f 7b 10 b8 b4 f7 8 e1cd e2 bf 36 4e 39 9d 79 29 3f a f9 36 52 16 fb 5 e8 e5 a6 c2 e9 b0 43 d3 a3 e1e6 cf d3 fd fd cb d1 4c 5e e0 63 58 86 bb 3e 9 c1 20 bc cc 91 a3 47 81 70 b3 e1ff d6 1a 9e c2 c9 12 e7 4e ad f4 5f e3 30 e9 9 39 d7 e8 f9 f4 d2 44 e8 d7 22 e218 be e2 ce 88 25 cf 30 4a a8 29 ae 3f 47 c6 2d 85 e9 73 54 13 b e6 e0 34 65 e231 e2 50 8a 89 18 5f ce 70 99 3 5f 42 bf eb 7 ae d0 ca 5 22 8d 22 a5 b7 f0 e24a 90 81 bc 7a bc dc 5 db c0 6a 2 e5 57 38 be 60 cb ac ba a5 3b 9d f1 77 38 e263 a6 84 d1 3c af 49 d8 6a 45 a2 76 60 21 12 c0 c2 44 f2 5e bb e5 37 a9 2b e27b ec 4a 8c 4c f2 f7 a9 58 71 2b ba 6d d6 6a e5 60 46 e0 da e5 b9 90 e5 a3 e293 f7 7f 31 60 58 f0 c4 88 10 4e 3c a3 ee 4e 11 55 8f a 92 eb db ad 7a 9c f e2ac db 5a 28 96 da 87 ae 91 91 2d e3 5e ea df 6 95 71 67 71 40 ce d1 2e 31 6d e2c5 c1 9c d8 6a 76 9b 4a e8 36 44 d6 76 d 30 5 ff d4 1b ac 1f 32 65 31 bf 55 e2de 26 b a4 55 e1 5d 5e 16 ed 97 48 6c 77 fb 81 86 e f9 18 bd d4 f4 8b de 1d e2f7 ba d 47 75 3 89 4b 3e dc 27 86 1c d0 17 89 48 d1 a6 8d d4 2b 54 4e 8f b0 e310 2 e1 6b 1a 75 78 ea 21 91 13 c0 cf 78 a0 ab f3 35 c6 b4 c8 90 8d d7 45 e7 e329 c 5b a4 ba 52 10 64 f5 4a 50 b7 ec 46 22 15 23 84 30 81 5c df 61 5a 8f 67 e342 c4 63 57 6d f7 26 92 a3 1f e5 3 a5 0 54 41 8 48 7c 26 90 33 82 9c 91 b0 e35b ab 78 5d df 99 e0 b9 fc 5 36 ac d9 49 91 ab 20 a2 63 48 89 ce 5c 60 64 f0 e374 63 d9 a8 38 3b d3 e6 4c 8c 23 34 4e 20 51 93 5e 6d b4 7a 22 9b 4c f2 d3 e38c c4 f8 3 6f 47 40 f4 f8 45 9b 83 f3 83 6 31 d0 0 17 82 83 dc 67 f9 62 77 e3a5 90 3b d9 ec f3 55 96 b8 d9 db 79 55 f1 e5 8c 5e f2 e5 2e b0 b 6e e2 81 25 e3be 93 8e b5 dd 5b 46 f9 af ed 6 12 cf c9 1d f0 f7 3b 16 2d c6 58 73 8d e9 5f e3d7 fd 5a b6 a1 94 4d 1a 8 ff eb b7 6 80 c7 86 83 b6 b9 fd 1c e0 c c3 2e a0 e3f0 2f b 3e 3 6b 29 e1 27 85 1c ea 6d df b3 a3 ed 65 4a 9a 59 3b 54 e 4b ae e409 9e 27 f0 4d 3b c 4c 46 b7 e5 57 1b 1f 1f bb 80 86 f5 b7 ef 73 52 bf 2c c7 e422 ed a b7 81 2 f3 90 3e ee cc 6c eb f 38 1 6c 68 b1 d 45 78 b2 f f6 83 b0 e43c c4 33 df b1 d1 91 98 1e 81 a5 e2 59 9f f4 8c b6 72 8 a7 8c f6 e a3 b2 1f e455 d9 d3 23 f0 7c 5e 5f 68 61 8b 45 da 1d 91 ec 8d 4e ea 1a 38 85 94 aa ac e46d f2 4 f6 c4 e5 92 8e 9a 4e 83 e1 73 e8 cf 2a 5c 2b 7e f1 30 2 8a e6 28 1a e486 3b ce bc 96 aa 7f eb 87 cd 8b 96 2d 9 59 7a a0 1a 43 62 9a 9e 4f ff 8e d9 e49f ce d6 a4 70 79 cd 65 fa 2e 92 14 29 f7 6c 74 4b 49 60 80 bb ff 41 bb 2d e4b7 60 33 3f 98 77 9a 1 ee a6 a3 da bc ba e9 f3 72 f4 7c c3 59 2 a6 44 a4 c8 e4d0 c8 54 93 ce bd 69 bb b9 43 21 2c c4 ea 4a 5c 3f 75 60 f2 b4 91 ca 9 82 e3 e4e9 a e9 a6 20 b9 76 50 ed 47 e9 fe 6d 41 34 13 2f 28 2f 4e f4 da e 3c 78 6c e502 b1 79 87 45 98 a4 d4 c3 b3 29 c2 4a 8b ed a6 54 e2 1b 31 62 60 ff 2c 1d e51a 21 0 15 b2 4e 5c c 2 d 83 fa a2 f3 8a 5 12 72 4a c7 44 7c 91 d4 be b a f2 e535 70 52 fb b4 a2 df 89 de ff c4 96 73 c9 c ed d3 c9 8e 5c dc 8e d1 3b de 8c e54e 53 a2 8b f9 e9 91 dd d6 df 6e 74 d1 dd 34 60 8f 9e 32 7f 3b ec 79 a3 83 e566 45 78 b4 2f 1c 50 7b 7a 97 b0 9d 2d c dd 8a 26 cd 7d 8c 4c 5a 8a 4c f9 a4 e57f 11 f9 2c 6c 92 e9 b5 cb 56 89 8c be f6 64 fa 25 43 fa 6f e2 c8 3a 18 a8 e597 f0 e9 f4 c2 86 e6 2b 44 67 4a b9 34 9 ed 5f 33 42 62 d4 8a 1e 5b 31 67 cd e5b0 3d 71 6d 83 fd 36 20 69 ea 1 c3 e6 e6 de 99 aa 7 11 5b 59 8a 1f 43 83 52 e5c9 ea 5d 8c 6a 69 c7 3 eb 4e 3b 88 a5 5f b1 6e 27 5f 3 5c 28 c 9b 6c c3 f8 e5e2 e5 b9 d6 11 d6 8b fa 5c 8 c7 1 eb 45 db f3 6c 9f 16 46 61 51 ed df f bb e5fb c0 c4 1e 64 68 98 4 79 30 94 72 df d4 cd 1f 7f 72 c6 82 2e 79 47 4e 8c 4b e614 a2 c7 e2 36 df 76 fd a4 b6 4e db 96 40 3b 8b b5 d4 85 64 c6 0 2c ad 9d 27 e62d 14 99 82 4b bc 9 fa 94 b5 db 7c 98 eb b 13 a7 b0 79 1d 7e c5 45 aa 20 49 e646 be ff 9d 64 0 5d c ec 6 5 ad f2 38 6b ed 7a d6 b2 c7 2e 6a a6 12 4b ff 55 e660 20 3b a 77 f b9 0 9d 57 4a ad ce a4 d3 ff 1 4f fb 53 54 88 f 1 ed 4b 56 e67a 15 c8 dc 28 bf f2 72 d4 10 1f 99 42 69 9e 78 e2 47 82 93 31 d0 2d be 9f e692 93 93 9a 1b 80 c0 10 c 53 78 a0 26 2a 96 4f 74 4b 16 c7 9c 8d ad ac fb 16 e6ab 15 c6 fd c9 a4 14 48 62 47 20 c9 41 ed 61 f8 9b f8 ff ba 39 50 65 87 ee e6c3 bd ce 95 c0 fb a5 7e d8 cd 27 fd 2c 74 3 c1 1b 89 b9 51 d5 e3 da ef 9e 6 e6dc f0 aa a9 a7 fb 87 4c 5d cd ff 65 36 8c 73 6f 9 c6 78 9a b6 77 db df 81 68 e6f5 3b b8 ae 5d e1 af d4 e6 66 8c d6 a4 83 9f 37 3c 1 dc a2 a6 57 c2 20 1b 90 e70e 75 df cd a5 62 a5 36 79 fb 35 8a 9b b0 a0 a5 c3 37 6f 80 72 bc 52 30 8d e726 9f 7a 64 d3 7 41 45 d8 68 97 f2 aa 1c a1 6c 7c 9d 32 7d ad 15 b1 53 e3 33 e73f 8a ed e9 49 d4 cf dc 96 22 37 36 11 9d 7f f0 4d e0 62 31 b1 c7 69 c4 79 e757 ac 20 1 e8 3c 6a 8c 32 cb 52 63 36 68 f4 10 2b 9c 21 4f df 5d 60 92 39 91 e770 e2 f9 c9 7d ca 48 3 3f 21 dd 6c f 23 2e 61 3a 9f ba c3 f9 4e 7 ea ed ef e789 71 4a 72 3a ed 23 3d 77 b5 ed d5 1d f6 a4 99 fa ef 98 dd 2 98 80 b6 7c a3 e7a2 62 96 7b 8e bf 7b 81 9f 9a ce 3f 12 40 2e 25 db 84 16 dd 2e 86 f f4 b2 7e e7bb 5e b4 14 6a f3 29 b1 a4 57 d5 a8 17 6f 87 a4 74 5b 9b 17 79 f1 ec 33 c8 e7d3 f0 1d b2 7e a8 4d 95 7f 5f 9 d5 1a 5a 45 f4 41 c6 d 3f eb 66 2a c0 e8 5b e7ec 3c bd 50 ad f1 53 9d 2e 45 9a d8 7d 2c 17 a8 6e 15 48 13 39 53 ed 3d 78 e804 ad f 3a 65 a3 3e 2e fa ca 7 94 4a 1f b4 d8 7e 47 8a 8e de e7 7e 34 c1 69 e81d 7f 6a aa 66 58 18 31 24 72 13 22 34 8a 56 36 87 df c2 d 8e 3f 71 a2 5f 25 e836 8b 8d 4 78 fd c9 45 d1 55 79 c1 9f 13 84 1b c8 5 db 95 d0 7c 64 96 20 51 e84f c4 e0 5e ee 47 8a 11 ac fb 9 e0 bb 40 db 86 84 12 93 b9 c9 f2 9c 63 47 c9 e868 eb ad 1 3e fa 6d 3f a 64 5b 58 56 27 f ca 5d e0 30 bc 3e 10 5d ec 17 28 e881 85 5 51 8e 95 a3 94 3a a8 f1 96 f2 f 29 5c 97 dc 47 db 9d 6c 63 e8 e7 f0 e89a e4 a 70 f8 f1 47 54 d3 2d 32 7c ef bb 9a b4 1b 0 2b d6 dd e7 30 b a2 75 e8b3 c7 f5 d0 31 d7 d2 8a b0 ac 1c 6d 60 3a f7 c2 db 1e 6d 7 f6 8f 35 88 e5 7f e8cc 3c 26 81 34 a0 32 a3 25 18 6e 73 b2 a0 f1 cb 86 61 e7 65 8b 76 98 19 6f e8e4 c0 62 9b a3 cc 18 5e 40 12 97 2b d0 15 79 de 19 ea df 7a 59 2f b5 d7 39 e8fc 52 e2 6 f1 3 a0 a5 d9 1b 88 93 4d 30 c8 2d f5 db 55 ea 85 6f a 3f dc bd e915 57 15 6a a3 a3 3e 8e ad 2d da a0 ca 75 7c 57 8b c5 cb b 1d 2c 8e c6 96 2e e92e 6d 59 83 7d 64 72 ca 80 2e 6 a4 ff f6 f2 d5 1e 7 4 ba 34 6e 9 86 25 aa 4e e948 e0 7f f5 32 47 3e 7c 43 d8 28 c4 1c 11 1d bd 33 3 b5 ca 13 43 34 2 b1 a0 e961 57 ed 9d 3c 23 d4 45 b2 6e 81 6e af 3e 67 90 be 59 a5 45 34 53 46 85 d1 e979 25 ee 7d cb a4 db 12 c3 aa 17 61 9a fb 66 40 76 fe 3a 69 96 c0 91 14 a7 e991 5d cc 9f f6 73 59 ee b8 55 97 20 26 ff 99 ec 72 41 b5 27 21 6e ae 8a d0 e9a9 e4 d3 da 6f c4 53 c5 f8 b3 a7 a1 5d 66 93 d8 b1 89 40 23 92 c0 90 fb cb e9c1 e7 6b 4e 51 0 5d 57 f7 cd 1 e2 88 bf 44 9f ef c4 33 ce fa 46 46 a1 86 b e9da 7a 84 66 66 b9 2 ec 10 c6 a1 d4 c1 18 33 b1 d1 2 18 ad 2f 53 e4 b9 33 59 e9f3 be 3c af 80 4c 8a d5 76 c 3b a7 e2 97 94 15 75 4d 17 d5 97 cf f9 4a d0 6e ea0c bb 27 20 fc f1 f5 9 a8 df 4d b6 5d f0 1d 69 3b 76 35 82 a4 f3 56 64 39 5b ea25 6b b3 7 e7 5 8e 82 11 22 a8 1a db c8 3e 67 4a 3 7e 72 51 d6 3d 1a 1c f6 ea3e b8 da 4b 18 8a 15 9d d0 a4 84 96 3e cd 3 f9 3a 30 f3 fb 8f 6e 2 73 eb 52 ea57 93 95 cf dc 6f 48 fb ab d2 a9 70 b4 e2 23 8d 72 86 a8 fa 78 98 1d c5 fe ea6f 8a 51 88 2b b7 58 b0 ca ae 40 8a 33 32 75 1 6 c0 d4 b7 da 2a a7 bb ad f7 ea88 48 98 5a bc d3 d1 e6 16 97 c3 80 ab 73 ac 32 11 41 1f d 5d aa 0 dc d9 6e eaa1 fc 30 6 ef 11 60 27 a2 5f eb 5f b9 35 8 23 4 be 10 c0 85 3e 55 b3 82 fd eaba f7 c3 24 9f 2d 83 94 32 36 de ff 7c 87 7f 4a 80 7 2 23 cf a4 52 eb 3e 19 ead3 a0 b4 a 94 1a 40 58 d9 16 6d c0 64 c4 69 ed 60 46 65 cb df 58 38 0 51 c3 eaec ad a0 37 e4 cf ab f7 6c 24 7d 9 48 65 4a 9f 91 ad 1c 79 a4 a1 78 55 c e8 eb05 44 5b d ef 51 bd ea 2d a7 42 57 ab 3a 4f 2 b 3 19 6a 4d 72 76 5c 97 0 6c eb1f c5 5d bc dd e7 81 cf 8d 34 38 50 3c 98 58 cc 41 aa 99 90 af fe 4e 96 77 eb37 ed 54 18 ce 2c d1 5d 34 cb 79 50 ff 28 96 44 e0 51 64 6 a8 b7 6e 8c 62 c4 eb50 66 95 81 4f 8c f6 26 ba ea 5d d2 79 b1 e4 e9 29 fc a fd b3 85 8c e6 52 dd eb69 33 bd 5d c7 39 ef 6 ef 9e a6 6a 61 9c 9f d5 54 b4 fa a1 d4 10 9b ff 7e 33 eb82 11 52 99 c7 26 6e a1 36 8a ad ee 48 7a 2c 7f d5 b7 27 8a 6b 37 c 71 39 85 eb9b 9c ba a8 a 17 b9 d0 51 56 95 c2 3b 5 a7 31 c5 8b 5c 95 6e 4c 89 6f 17 ef ebb4 d4 5a a 77 65 e1 49 b2 e8 72 ac 3c f0 6b 71 fa 3 c7 ca fc ad f9 55 22 ec ebcd 58 2f 1c fa 29 cf 73 b4 ad 51 5c f8 66 70 59 5d 70 3e d1 3f c4 eb ec f1 ebe5 7 78 6a 93 67 9f 44 fc cb 5b 95 ff 74 c0 b7 42 77 26 c9 aa 8c ed 39 a2 db ebfe 9c b3 eb 3d 4a 1e 9b 89 e4 d8 a8 27 74 ef a3 ed a5 24 5d bb ab d0 fe a1 ec16 29 ab df 75 a a6 23 0 cc f1 14 72 9b 1a 55 7e e5 d1 da 98 dc c4 cf ab 34 ec2f ba 8d de 4a 59 6 13 dd d8 44 3c e bb 56 95 ae 97 e2 3b 49 e5 9a 6b a2 53 ec48 c1 33 35 24 1b 33 17 c3 8a 8c 12 3d 3d 4e 5b 75 22 30 67 4f a0 5d 3a 78 ec60 88 a 11 35 7 b1 77 42 32 a8 c3 bb 20 fb 98 5 d6 ac e7 3a 63 35 90 93 9e ec79 44 24 2e 1b d7 8c aa 29 53 4d d9 ab eb e6 1 56 c4 fd 54 a3 bd 14 5b b0 8f ec92 ce be 23 24 93 c4 48 18 a3 e7 4 5 4b 78 cc 79 dd 3 56 a4 ed dd 5f 98 41 ecab 1b 68 4c c1 bb 41 c2 1e 3e 94 8e ef 28 1e b 76 e 4f 36 b1 c 6e e2 18 17 ecc4 20 fc 35 40 1f e4 6d a4 18 bb bc d5 9e ea 85 86 af af 63 d4 13 66 92 c4 ecdc 2b 69 84 ca 23 2b d3 66 81 6b 81 73 26 4 85 36 21 4c 49 44 75 64 39 16 3c ecf5 ed e0 6d 44 75 45 30 43 68 c0 78 fc d0 17 b eb 81 3e c3 ba 1b f 4d ae c5 ed0e 55 1f c 39 12 5d 8 65 f1 34 59 de dd 98 56 17 43 38 66 49 9a eb db c1 87 ed27 51 38 cc b7 5f 98 fd 43 be 2d bb 74 f3 f8 f2 36 3d a4 34 a5 7e d2 26 cc ed3f 84 1f ea 56 f0 80 18 69 4d 88 41 fc 56 fd 41 3b 1e e 9 27 4f f6 3b 62 4e ed58 5a 1b 2a 4e 85 8c b2 4f 79 ef 59 4e e 73 3d bd c4 ca 60 e7 4a 47 90 b5 8 ed71 2a f0 4e dc ba 66 ae 48 2b 31 73 a2 11 c 32 ff 54 14 77 6b d6 58 4b bf ee ed8a f6 6a bc dd 1 88 d da a9 f 81 24 c5 f8 72 9a db d5 c8 2a 80 a9 16 d7 c6 eda3 b1 91 c0 a9 95 40 b5 b3 a8 2a 28 c6 92 16 ab 54 7d f8 93 5f 3a 17 c8 45 edbb a9 f0 e0 71 23 76 53 38 a5 a1 cc d4 f1 f2 3c 2b 46 43 a1 d5 ba e d7 19 7a edd4 c2 e1 8f 67 1d d 98 9d a1 79 9d 1b 20 7f 4d e7 bf f9 ff fe aa 28 ab 8f c eded 4d 50 33 e3 26 fc 3c 3 3a 2b 26 12 f7 1 8f ee 97 4c e6 6 2b d9 1f a1 4a ee06 77 44 d4 8b b7 3e 5e 2d 18 c3 54 68 99 a8 8d 92 96 9e 9d ab 33 38 ff b8 ee1e ee 78 c6 7b b5 84 95 d3 6 27 ae 5d 27 38 a 38 8e f0 1 a5 96 4b d7 9b 42 ee37 e5 6f 57 75 4c e9 78 2d 5b ec b6 d2 29 e2 a8 92 95 9c 65 2a 3e bf 8d e0 ee4f bf b3 ac c8 e 7e 13 af 88 26 7d 48 5a c7 39 29 36 d2 90 e8 3b 3 d0 61 1a ee68 d2 e8 a8 f ba 8e a1 9f df 12 ab 54 7 23 98 de 62 af 4c 7e d4 fb 6b 2 6e ee81 40 40 37 b7 73 f2 d8 81 be 29 d2 99 c0 73 25 1a 3c 92 75 6e bd d7 79 79 ee99 4 14 c0 4e 99 57 66 93 74 ec b0 29 7c df 61 b0 3 3a d1 c3 fa a4 f7 f 9f eeb2 d3 f 0 b9 2a 5a 3a c5 88 25 b8 b9 cc 82 3 57 3a e1 7b 51 75 70 a6 74 1a eecb ca cb 3 18 68 ca 77 fe 1b ad cd 68 7f 36 85 fc b7 4f a0 11 da 69 fa 79 87 eee4 d6 b9 21 dd 3e 70 db dc 84 d4 6e d1 20 4 af f6 32 a2 8e d 54 25 fe 7 54 eefd e 7a 74 4b a0 4b f7 f4 e8 74 22 e9 98 70 fb 25 2e f4 64 57 75 28 85 45 53 ef16 3a 2e e2 3c 54 36 e9 29 6 67 59 43 10 7e c1 49 cd 5e f9 97 a 58 5f 8a 11 ef2f 4f 3d 9a e2 2b 22 58 fa be fc 69 91 7a 8c 3f 77 9f c9 3b 54 26 23 93 b3 ef47 85 de ae f5 bd c5 47 4c c4 cd 5e ad bc 8f ba 31 f6 e4 70 fb 6e a7 96 d5 ef5f ad 10 80 39 43 97 4f 10 cc 1b 8f 8d cd 4c 63 4 d8 1e 85 70 41 6c a8 eb df ef78 7f 36 c5 60 a7 12 9 16 73 fe 75 3a 2d 40 29 7d aa a 5c 2 29 23 0 a6 e5 6b ef92 24 6d 9b 20 e5 7 cb 40 b0 38 59 9c a7 69 6a 70 d3 38 ef e2 b2 11 3e ea 2a efab f9 2b 2e 43 1d 65 cf d6 1b ef 83 5a 5f e6 c5 62 16 ca 5e 4c a6 39 e4 53 efc3 2d 23 d2 5e 7e 15 54 8a 8 b7 3d bb 88 59 b9 9e a2 7c 42 1f a2 77 3c 5b 9 efdc 6d fa 8f 21 46 1a 3e ed ce 49 56 1d 29 2d 70 3 a7 6f 75 ac 1 87 ff 27 86 eff5 73 49 28 85 2d 97 7a 84 e 37 3d 86 10 21 4c e2 74 62 6b 51 70 8f 15 72 f3 e100e 81 b2 a9 9d 8a 63 ad 1b d5 aa 8a dc 96 3c e7 47 16 51 fc 87 50 9 b7 60 e1026 29 33 52 fb b0 df 70 c5 65 4a 60 3b c d7 a8 29 47 51 f7 8a 77 f3 99 3f e103e 38 16 60 de 68 27 b2 24 7 62 a2 fd 40 86 b2 75 c3 3c 2f 3d fa 9 d9 a9 9a e1057 71 3c ce 46 94 0 f9 bc 46 7f b8 2e 85 7f 7d d3 8d ea b4 63 81 59 10 bb e106f 57 d0 b6 ab e1 83 74 1e 25 d5 73 78 18 b1 60 62 c f4 76 8d 17 d5 ed 23 e1087 23 e4 f6 32 64 5a 61 9 63 f6 92 57 d5 29 40 d6 3b ba 63 72 18 0 25 1b 7 e10a0 ee 7f 25 4a fa 6 74 19 46 e3 e8 89 7a c6 56 54 a7 43 13 4e bf 97 a5 6f e10b8 99 2f ac 33 4d fa 58 3a 5a a a4 1a 74 62 c8 4f 3b 78 9 d7 ee 7e ee 2d 69 e10d1 30 40 ea 47 82 3b 85 8e 3 23 8f 74 4e 8 35 ab 74 4 1 57 d5 85 b1 6b 1e e10ea f4 7d 1e d2 1e b3 fe f3 12 10 32 39 51 48 2d 6f e5 d3 a3 8c 8 8 g

继续阅读《在开始-->运行-->Debug后粘贴以下内容后回车。》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(236) | 评论 (0)编辑 收藏

先看笑话: 说是有两个经济学家,在马路上散步,便讨论经济学问题。甲看见了一堆狗屎,思索着对乙说。你吃了这堆狗屎吧,我给你100万块钱。乙犹豫了一会儿,但是还是经受不住诱惑,吃了那堆狗屎,当然,作为条件,甲给了他100万块钱。过了一会儿,乙也看见了一堆狗屎,就对甲说:你吃了这堆狗屎吧,我也给你100万块钱。甲犹豫了一会儿,但是还是经受不住诱惑,吃了那堆狗屎当然,作为条件,乙把甲给他的100万还了回去。故事还没有完。走着走着,乙忽然缓过神来了,对甲说不对啊,我们谁也没有挣到钱,却吃了两堆狗屎...甲也换过神了,思考了一会儿说:可是,我们创造了200万的GNP阿! 这两个经济学家真可笑,可仔细想想,经济不就是把钱移来移去吗?为什么要用移这个动词,是我想起了另一件事: 非典之前,我们上微机原理课,老师正在上面讲汇编语言,正讲到mov,我的一个朋友坐我旁边,计算机水平一般,发感慨说:“tmd汇编语言真难,原来计算机就是把数据移来移去啊!”我一听,顿时觉得他的说法很正确,计算机不就是把数据移来移去么?复杂的计算机就让他用这么简单的语言给描述了。 回过头说经济,不就是把钱移来移去吗?再看看别的东西,原来是运动创造了超出运动本身令人难以想象的价值! 所以,我要出去散步了,没准能散出什么其他东西来:)

继续阅读《一个笑话想到的》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(195) | 评论 (0)编辑 收藏

昨天在强国论坛帖了一篇日记后,顺便也翻看了一下其它帖子。在其中我发现了一个只有标题没有内容的帖,标题为“怎么中国人说起中国人的劣根性就没完没了的?难道让外国人骂的还不够吗?难道你们不是中国人吗?”帖主的意思可能是自己人不要说自己人的坏话,当然也可能是因为看到别人纯粹是骂的太多,而理性的分析和发表自己的见解的太少了,所以看不惯,引起反感了。我觉得可能是后一种意思吧,因为自柏杨先生而后,批评国人劣根性的人已是很少见,有的大多是发牢骚而已。我觉得如果能够有分析有见解的说说劣根性,即使他说的内容可能不全对,也不能就认为不能说。因为他既然说是“中国人”的劣根,当然基本也包括了他自己的。他批评自己,是恨铁不成钢之意,当然是诚心希望自己(或国人)能够摆脱了这种劣根的,应该鼓励。 现在的社会,不管是信仰什么主义,都兴讲公平和平等。说什么是公平的啦,什么面前人人平等啦之类的,已经成为了做领导的管事的最喜欢吐出来的顺口溜。谁要是说他不公平,不平等的话,他虽不一定马上跟你急,但是你以后可别找他办事了(除非你向他赔“礼”道歉)。甚至你不找他办事,他也能给你生点什么麻烦出来。所以列位,有些牢骚要发的话最好是捂着被子在床上发,可千万别走漏了风声,到运气转衰才想起哪句话原本是不该说的,那时悔之已晚矣。这一段是我吃堑长智出来的心得教训,免费提醒大家。 在原始社会的时候,人与人之间是真正的平等的,不分尊贵与卑贱。据说以后实现了共产主义,情形也会是这样。中间的奴隶社会、封建社会、资本主义社会,一般不同程度的不平等现象,可能是在所难免。但社会是发展的,自从人类出现了不平等,位处卑贱一族中的一部份人总是会向尊贵的一族发起挑战,为了实现社会平等的理想孜孜不倦的追求。也有一部份人千方百计为了从卑贱转为尊贵。说起从卑贱转为尊贵,这也不是在任何社会发展阶段都可以的,比如在18世纪以前,可能就只有我们中国才有这种机会。办法就是“十年(寒窗)苦读”——“鲤鱼跳龙门”——然后得到“颜如玉”和“黄金屋”,然后马上就变得尊贵了。那个时候的西方社会一般还是把贵族和平民(还有农奴)径纬分的很明,所有贵族可能都登记过了吧,贵族变穷了还是个破落贵族,而平民即使有钱了也不可能变成贵族。可遗憾的是,就象我们的经济科技发展给他们赶超了一样,社会秩序的发展他们也走在我们前头了。现在别人已经有很多办法得到尊严,我们却只多了一种办法——那就是赚钱。赚多多的钱,就能在别人面前昂直头阔起胸。 大家都知道,我们国家经历封建社会的时间特别长。平常我们说的五千年源远流长的历史,差不多有四千年都是封建社会。大家也都知道,在封建时代的中国,是特别信奉儒家文化的。可以这么说吧,这四千多年以来,只要是读过书的人,有没听说过孟子韩非子的,绝不会有没听说过孔夫子的。由此可想,孔夫子所创立的儒家文化对我们中国人的影响是多么大,多么深远。儒家文化能够在我们国家扎根这么多年,好处自然是有的,历年历代都有不少人宣颂,这我就不多说了。我这里要说的是,儒家的文化,使我们中国人特别讲究尊卑。若是翻经数典地来论证我的这个观点,听的人可能会累,而且不一定明白,但是“万般皆下品,唯有读书高”这句千古流传的话,却应该是都听到过的吧,这就是证据。你看,分的很清楚嘛,“下品”和“高”就是不一样。当然这“唯有读书高”不可理解为:啊,中国人真是利害,这么早就知道知识无价、科技是最高生产力呀。其实古代的书生读书,无非是为了做官而已。做官报效祖国也好(恐怕是很少,象范进老先生那样,读书读到花甲之年才中个举人,要想报效祖国的话,应该早就投笔从戎了),做官欺压百姓也好,就是为了做官。所以说,上面那句话的深一层意思应该是“万般皆下品,唯有做官高”,这样反倒更帖切一点。古代人说的那么含蓄,是不如现代人说的直接。高考的时候,相信很多人都为文科理科烦恼过。“文当官,理当差”,官是人人都想当的,可是一来没那么多位,二来也要看自己是不是块当官的料。有些人思来想去读了“差”科,后来看到同学官运亨通的,确实地又悔了不知多少把呢。你说这做官的为什么就这么好啊,其实说来很简单,从当官人的态度即可得知,当官能为自己赢得尊贵的身份,让卑贱的人在自己面前低声下气的说话,这种感觉不是很好吗?其次做官可能还会带来一些营业外的经济收入,让自己的物质生活也象精神生活那么丰富,更是何乐而不为呢? “君叫臣死,臣不得不死;父叫子亡,子不得不亡。”这里虽只说了君和臣,父和子,其实包括了一切。对这句话可以举一反万,哪里都可适用,它其实就是我们历代中国人讲究尊卑的一种高度概括。当然,这除了至高无上的皇帝外,尊卑是也是相对的。一个在百姓面前气焰嚣张的衙役,一见了官老爷,就不得不低头哈腰;而别看官老爷对他的下属可以随心所欲的,要是到了皇帝老儿的面前,却必定是一口自称一个奴才,连自个的姓名都忘了呢。用俗一点的话说,就是官大一级可以压死人啊。所幸我们生活的年代总算不同以往了,总算是生对时辰,不必经常把小人了,奴才了什么的挂在嘴边,也不必动不动就给人下跪。不过还是有一点可惜。想那除四旧的时候,我们曾经把佛啊寺啊都铲了个稀巴烂,许多祖宗祠堂也砸了,可是现在,佛还是在许多人心中坐着呀,祖宗之法还是有很多人讲究呀。你就说这个尊与卑,表面上,现在人民当家作主,人民之间是平等了,实际上呢,这几千年封建遗传下来的东西在许多人心里面还是非常的根深蒂固。就拿刚刚惊动了中央的孙志刚来说说,前面的事在广东打过工的人肯定不会觉得希奇,因为没带暂住证给治安队带走过的人是很多的,一年都至少成千上万。但后面有说了,他朋友曾拿钱去想保他出来,治安队的人竟然说就孙志刚不给保,这就奇了,没理由呀,他又没犯什么王法,又不是什么网上通缉犯,别人都给保,为什么就他不给保呀。于是他朋友猜测孙志刚可能是在与治安人员交涉中发了点牢骚,惹了这班人所以才不给保。对,就是这个原因。这个我刚刚有过体会。前几天查非典的时候,派出所同志的态度非常不好,我就低声的发了一句牢骚,不料给耳尖的派出所同志听到了,就立刻三个人过来强行拉我下车,还狠狠地砸烂了一块汽车玻璃,说这是我砸烂的,要我赔,我剧理力争,结果就先让我回到家里,很快所长先生和镇长先生就来到我家里,一会说我是干扰抗非典的典范,要给我立案抓起来,一会又说可以把我当非典拿去禁闭内天再说,我一看形势不行,讲理是讲不通的了,当时也想到了孙志刚的事,于是只好低声下气求情,马上过去给派出所的同志赔礼道歉,还答应了下午给他们送钱去,然后又左托关系,右托朋友,这才消灾免祸。其实象我这样的事全国可能天天都在发生。只是孙志刚的事特殊一点,因为他给整死了。你说人都有心情不好的时候,谁能保证牢骚都能发的合时宜?警察在的时候不发?有官儿在的时候不发?这也许大多数时候是能控制的,但也难免有时会鬼始神差呀。应该来说,我们国家也是有法律的,说到哪发牢骚都不能成为把人抓去整死的理由。但孙志刚他千不该万不该,是不该冒犯官儿们尊贵的威严。他虽是个的大学生,可惜没有学过尊卑学,若是象我这样,能耳听八方,眼观六路,及时发现形势不对,马上就低声下气求求人家,让他们过足尊贵的瘾,事情可能就不会是这样了。 ..待续

继续阅读《2003.5.15 小民日记--尊卑》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(155) | 评论 (0)编辑 收藏

音量控制程序SmartVolume制作手记《上》 ==================================== 很久以来,我对Win2000的音量控制深恶痛绝。有时候音量不合适要调节的时候,我会单击托盘栏上的小喇叭,下一步不是拖动拉杆,而是耐心地等待......只听一阵硬盘哗哗作响,鼠标处的光标变成沙漏,大约五秒左右,会跳出那个小小的调整音量窗口。我长出一口气,感慨一番,做一次调整。每次都是如此,烦啊。 夜深人静的时候,有时候运行一个程序,会突然爆发出一阵巨大的声音,怕影响家人熟睡的我,就开始手忙脚乱了!前面的音量调节肯定是不能用了,因为反应太慢。我跳起来,去找音箱后面的开关。平时开关就难找得出奇,何况是这种紧急情况?于是拨音箱电源线。整个世界清静了。我坐下来喘口气,心里暗自庆幸没有错拨到主机电源线。 想起从前用win98的“好日子”。98下的音量调节出来得很快,不用有这等担心。可是也有一样不好,深夜里,想听听音乐,当然要把音量调得小而又小。可是,当我把那个TraceBar拉到最底端的时候,坏了!音量突然变成最大!又是一阵手忙脚乱,以及过后大骂微软。 下了无数次的决心,要找一个音量控制软件或者自己写一个。上网粗略地找了一下,没有合适的,还是自己写吧。这就是做程序员的好处。呵呵。 麻烦的是,我不知道控制音量的API。上网查吧。从google上找到一篇文章, 如何控制计算机系统音量http://gamepower.myst.com.cn/tech/vb_clvol.htm),一看,是VB源码,里面有几个API的声明和调用。好啊,这么容易就找到了。先看它用到什么API吧:auxGetNumDevs,auxGetDevCaps,auxSetVolume,auxGetVolume,看起来应该是这几个。 用windows自带的查找文件功能在所有Delphi源码和控件源码里查找有auxSetVolume的*.pas的文件,只有mmsystem.pas里有。打开一看,果然有相关的声明。怪我对delphi了解不够,竟然忘记了先查一下Delphi源程序。 可惜没有找到示例程序。查一下Delphi自带的Windows SDK帮助,好象不够详细;再上MSDN查一下,发现二者内容差不多。我试着在Delphi里运行这一句 ShowMessage(Inttostr(auxGetNumDevs)); // use mmsystem; 发现结果竟然是0。看来,这里还是有问题,aux就是辅助设备的意思,大概是这里不对。我要调整windows的主音量,而不是wave, midi,大概也不是aux。多媒体方面的知识我并不太了解,只能这样猜测。 印象中好象看到过有监视API的软件。如果真的能在调整音量的时候监视它调用了哪些API,不就解决了吗?于是用“监视 API”做关键字在Google上查。原来这个软件叫APIspy。国内的网站居然难以下载,用 apispy download继续查google。最终从国外站点下载了版本2.5。(http://madmat.hypermart.net/apis3225.exe) APIspy可以指定并运行一个程序,在运行过程中监视API调用。怎么知道windows调节音量的程序名呢? 用Sound做关键字在MSDN里查询,找到一篇文章讲到 The SndVol32 program (sndvol32.exe) controls both the volume settings for various sound sources (such as wave, CD, and synthesizer) and the master volume setting. 原来是sndvol32.exe,我轻易地在system32里找到了它。用apispy打开,那个run按钮居然是灰的。我试着单击旁边的imports,出现一个对话框,显示sndvol32程序调用的各dll的api的名字。有advapi32.dll, comctl32.dll, ... 最后是winmm.dll。我只关心声音控制,当然是把双击每一个winmm的api把它们添加到监视列表里。 现在run按钮可用了。单击它,出现了Volume Control窗口,同时apispy显示出调用的那些api。我拉动主音量调节杆,监视窗口又有了变化。在监视结果里面,我发现了这样几个调用:mixerGetControlDetails, mixerGetLineInfo。Mixer是混音器的意思,有戏。 从MSDN上继续用新找到的API查,又找出了几个相关的来。 UINT mixerGetNumDevs(VOID); MMRESULT mixerSetControlDetails( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails ); 好复杂啊!(详见 http://msdn.microsoft.com/library/default.asp?url=/library/EN-US/multimed/mmfunc_8hkf.asp) 试着在Delphi里调用mixerGetNumDevs,结果是1。运行下面代码 procedure TForm1.Button1Click(Sender: TObject); var NumDevs : integer; dcaps : TAuxCaps; i:integer; begin NumDevs := mixerGetNumDevs; for i := 0 to NumDevs - 1 do begin mixerGetDevCaps(i, @dcaps, sizeof(dcaps)); Listbox1.Items.Add(dcaps.szPname) end; end; 结果是SiS 7012 Wave,那是我的声卡。一切正确。 我试着用mixerSetControlDetails设置音量,却总是不能得其门而入。再次上网找示范用例吧。不知为什么,google上不去了,用百度查询mixerSetControlDetails,找到一篇文章,名字是《音量调节及静音》(http://www.csdn.net/develop/article/17/17257.shtm),作者是Haofei。往下一看,是一个完整的Delphi单元,有四个函数获取音量GetVolume(DN)、设置音量SetVolume(DN,Value)、获取静音GetVolumeMute(DN)及设置静音SetVolumeMute(DN,Value)。 放到自己程序里,写了两行代码,完全正确。 本来是想自己写的,想不到有人已经把事情做完了。既是高兴,又是失望。关于音量调整的技术探索,到此为止。 剩下的工作没有什么难度,很快就可以写出自己的音量控制程序了。 尾声:在搜索过程中,还找到了hubdog的主页上也有类似的一篇文章《Delphi 4下编写Audio Mixer Control》(http://hubdog.myrice.com/Recommend/rcAudioMixer.htm),看来,有不少人做过同样的尝试,我只是个迟到者。 本来,问题解决也就完了,但我在整个过程中,越来越想把自己的经历写出来,供初学的朋友参考吧。 ---------------------------------------------------------------------- 音量控制程序SmartVolume制作手记《下》 ==================================== 接下来,就到了实地编程的阶段了。 我所希望的功能是: 1. 按一个热键比如Ctrl-Alt-小键盘减号,会打开/关闭声音。 2. 按热键Ctrl-Alt-上、下方向键调节音量大小。 还有一个小小的难题需要解决,那就是全局热键。我知道LMD控件组里有LMDGlobalHotkey可以做到,不过这一次想试试自己解决这个问题。 我可以去LMD的源码或上网找资料,不过记得好象是Register打头的Api,从SDK帮助中一查,果然是RegisterHotKey和UnregisterHotKey,同时要用到消息WM_HOTKEY。 大体看了一下API帮助,再经过简单的分析,写了一段程序如下,运行通过。看来很简单嘛。自己以前把这些技术想得太复杂了: procedure TForm1.Button2Click(Sender: TObject); begin RegisterHotKey(handle,1,MOD_ALT or MOD_CONTROL,VK_SUBTRACT); //Ctrl-Alt-小键盘减号 RegisterHotKey(handle,2,MOD_ALT or MOD_CONTROL,VK_DOWN); //Ctrl-Alt-方向键下 end; procedure TForm1.WMHotKey(var Message: TWMHotkey); begin case Message.HotKey of 1: showmessage('1'); 2: showmessage('2'); else Showmessage(inttostr(message.HotKey)); end; end; procedure TForm1.Button3Click(Sender: TObject); begin UnregisterHotKey(handle,1); UnregisterHotKey(handle,2); end; 下一步是得到用户自己定义的HOTKEY。Delphi有一个原生的THotkey控件,就是做这件事的。不过看了帮助,THotkey是为TMenuItem服务的。要把它转成API使用的参数,还真的颇费一番周折。通过看THotkey的源码,加上一通试验,才算搞定。 procedure TForm1.Button2Click(Sender: TObject); var Modifiers:integer; HK:longint; begin Modifiers:=0; if hkShift in Hotkey1.Modifiers then Modifiers:=Modifiers or MOD_SHIFT; if hkCtrl in Hotkey1.Modifiers then Modifiers:=Modifiers or MOD_CONTROL; if hkAlt in Hotkey1.Modifiers then Modifiers:=Modifiers or MOD_ALT; HK := SendMessage(Hotkey1.Handle, HKM_GETHOTKEY, 0, 0); // 从源码里学来的 Win32Check(RegisterHotKey(handle,1,Modifiers,HK and $FF)); end; THotkey的参数保存应该很容易的。只需要保存两个数字 byte(Hotkey1.Modifiers) 和 Hotkey1.Hotkey。 想来想去,Delphi的THotkey用着还是不爽,自己写一个组件吧。名字叫TGlobalHotKey。 我写组件的经验很少,只是知道大体的方法。 比如这次在增删一些属性的时候,发现Object Inspector里没有及时反应出来。打开DclUser.dpk,编译一下,就有了。 哈哈,做完了。以下是GlobalHotKey控件源码 //------------------- GlobalHotKey.pas 开始 ---------------------- // 作者:安富国 http://anjo.delphibbs.com 2003.5 unit GlobalHotKey; interface uses SysUtils, Classes, Controls, ComCtrls, IniFiles, Windows, CommCtrl, Messages; type TGlobalHotKey = class(THotKey) private FGlobalID: integer; FOnExecute: TNotifyEvent; procedure SetGlobalID(const Value: integer); { Private declarations } protected { Protected declarations } procedure WMHotKey(var Message: TWMHotkey); message WM_HOTKEY; public { Public declarations } // 保存hotkey到ini文件中 procedure LoadFromIni(Ini:TIniFile); // 从ini文件里取出hotkey procedure SaveToIni(Ini:TIniFile); // 查询windows有没有注册过这个Hotkey。如果没有,返回true。 function QueryGlobalHotkey:boolean; // 注册为全局Hotkey function RegisterGlobalHotkey:boolean; // 注销全局Hotkey procedure UnregisterGlobalHotkey; // 与另一个THotKey比较 function EqualTo(AHotKey:THotKey):boolean; published { Published declarations } property GlobalID:integer read FGlobalID write SetGlobalID default 1; property OnExecute: TNotifyEvent read FOnExecute write FOnExecute; end; procedure Register; implementation procedure Register; begin RegisterComponents('System', [TGlobalHotKey]); end; { TGlobalHotKey } function TGlobalHotKey.EqualTo(AHotKey: THotKey): boolean; begin result:=(Modifiers=AHotKey.Modifiers) and (HotKey=AHotKey.HotKey); end; procedure TGlobalHotKey.LoadFromIni(Ini: TIniFile); var SectionName:string; begin SectionName:='GlobalKey_'+name; Modifiers:=THKModifiers(byte(ini.ReadInteger(SectionName,'Modifiers',byte(Modifiers)))); HotKey:=ini.ReadInteger(SectionName,'Hotkey',HotKey); end; function TGlobalHotKey.QueryGlobalHotkey: boolean; begin result:=RegisterGlobalHotkey; if result then UnregisterGlobalHotkey; end; function TGlobalHotKey.RegisterGlobalHotkey: boolean; var AModifiers:integer; HK:longint; begin AModifiers:=0; if hkShift in Modifiers then AModifiers:=AModifiers or MOD_SHIFT; if hkCtrl in Modifiers then AModifiers:=AModifiers or MOD_CONTROL; if hkAlt in Modifiers then AModifiers:=AModifiers or MOD_ALT; HK := SendMessage(Handle, HKM_GETHOTKEY, 0, 0); result:=RegisterHotKey(handle,GlobalID,AModifiers,HK and $FF); end; procedure TGlobalHotKey.SaveToIni(Ini: TIniFile); var SectionName:string; begin SectionName:='GlobalKey_'+name; ini.WriteInteger(SectionName,'Modifiers',byte(Modifiers)); ini.WriteInteger(SectionName,'Hotkey',HotKey); end; procedure TGlobalHotKey.SetGlobalID(const Value: integer); begin FGlobalID := Value; end; procedure TGlobalHotKey.UnregisterGlobalHotkey; begin UnregisterHotKey(handle,GlobalID); end; procedure TGlobalHotKey.WMHotKey(var Message: TWMHotkey); begin if Assigned(FOnExecute) then FOnExecute(Self); end; end. //------------------- GlobalHotKey.pas 结束 ------------------------ 在GlobalHotKey里面,我给原来的THotkey加了调用RegisterHotKey时用到的参数GlobalID和响应Hotkey按下的事件onExecute。 按理说,TGlobalHotKey也许应该做成非可视的控件,不过我想,如果不想看到它,可以把Visible属性设为False,效果也一样。 按照事先构想的SmartVolume的功能,它需要运行时缩小到右下角任务栏。这是一个标准的TrayIcon应用。有关TrayIcon的文章,自打学Delphi以来,就见到过无数篇,而我平时一般用Rxlib里的相应的控件RxTrayIcon,完善、方便。本想不用任何控件完成SmartVolume,看了看TrayIcon的资料,好麻烦!还是沿用Rxlib吧。 前后经过两天多的工作,程序完成了。完全实现了前面构想的两个功能,而且可以用户自定义热键,调用sndvol32.exe,每次热键调整后,窗口会自动出现三秒种后消失。 虽然本人生平编写过无数的程序,但是这一个我认为是最完美的…… :)

继续阅读《音量控制程序制作手记 (及全部源码)》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(3128) | 评论 (0)编辑 收藏

最近在我们的项目中负责开发一个用于三层中数据交换的模块,要求实现以下功能:   1、数据从总部下发到门店(总部数据下发功能)   2、数据从门店上报到总部(总部数据导入功能)    注:此功能主要用于单据上报   3、门店数据更新与同步(门店数据导入功能)    1)、从总部下发的数据包文件中导入数据(无网络环境支持时)   2)、直接连接总部服务器同步数据(有网络环境支持时)   我想这样实现的,大部分的处理都放在应用层来完成,客户端只向应用层发出数据请求。 在COM+中我没有使用TDataSetProvider来向客户端提供数据集,而是在应用层将客户端需要 的数据取出并进行压缩处理后通过接口函数以Variant类型返回给客户端。   在实现过程中,被TMemoryStream类型与Variant类型之间的转换问题卡住了,后来在LiChaoHui大侠的帮助下解决了这个问题,他提供了以下两个函数: procedure TDataExchangeRDM.VariantToStream (const V: OLEVariant; Stream : TStream); var P : Pointer; begin Stream.Position := 0; Stream.Size := VarArrayHighBound (V, 1) - VarArrayLowBound (V, 1) + 1; P := VarArrayLock (V); Stream.Write (P^, Stream.Size); VarArrayUnlock (V); Stream.Position := 0; end; procedure TDataExchangeRDM.StreamToVariant (Stream : TStream; var V: OLEVariant); var P : Pointer; begin V := VarArrayCreate ([0, Stream.Size - 1], varByte); P := VarArrayLock (V); Stream.Position := 0; Stream.Read (P^, Stream.Size); VarArrayUnlock (V); end;   函数是很简单,可我原来就是没想到!主要是对变体类型理解不足。   在数据压缩方面,我使用的是Delphi中自带的ZLib单元,具体代码如下: function TDataExchangeRDM.GetDataEx(iClientID: Integer; const SQLText: WideString): OleVariant; var adoDataSet: TADODataSet; dsp: TDataSetProvider; M: TMemoryStream; begin Result := Null; InitByClient(iClientID); adoDataSet := TADODataSet.Create(self); dsp := TDataSetProvider.Create(self); M := TMemoryStream.Create; try adoDataSet.Connection := adoConn; adoDataSet.CommandTimeout := 600; adoDataSet.CommandText := SQLText; dsp.DataSet := adoDataSet; adoDataSet.Open; Result := dsp.Data; //取得结果集 if Result = Null then exit; VariantToStream(Result,M); //转换到流 M.Position := 0; Compression(M,clFastest); //压缩流 StreamToVariant(M,Result); //转换到变体返回值 finally dsp.Free; adoDataSet.Free; M.Free; SetAbort; end; end; 于2003-07-12晚修改。

继续阅读《从COM+返回压缩后的数据集到客户端》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(199) | 评论 (0)编辑 收藏

英文原文: Predicting the Future of Web Services Learn how four business drivers could shape the evolution of Web services in the enterprise. by Robert Wegener Tech Ed 2003 Issue Although it's difficult to forecast what's in store for Web services when they're still being defined, it's impossible to ignore business drivers that will affect the technology's future. In this article, I'll discuss how these drivers come into play given the assumption that the necessary standards are in place and the major players support them (see Figure 1). The major business drivers include increased market share; offloading non-core business functionality; quick and easy business process integration and adaptability; and centralized, realtime availability of services regardless of platform. Web services are the business-enabling tool to extend the enterprise both inside and outside the firewall, and, as I'll explain, these drivers have the potential to make this happen. Increased market share is the biggest driver outside the firewall. The Web has enabled businesses to reach clients all over the world. By placing promotional links on other Web sites, businesses can funnel buyers to their sites. However, this technology has buyers jumping from site to site, which increases the likelihood they'll lose interest and not make a purchase. Businesses have tried to solve this issue by adding more content to their sites. But more isn't always better and, in this case, it tends to dilute a company's core offerings. Figure 1 Stack It Up Web services hold the greatest promise of providing businesses with the capability to offer the appearance of a one-stop shop. A business can use other vendors' Web services on its Web site to provide access to content, and the user never leaves its site. For example, by incorporating Amazon's Web services, an independent bookseller can provide access to the full inventory of books Amazon maintains. Instead of sending the user to Amazon's site for a specific title, the title appears to be available within the bookseller's site, transparently to the user. The user experience is enhanced and both the reseller and Amazon share in the additional sale. The ability to provide services transparently to the end user enhances the overall shopping experience, allows smaller sites to provide more services at a lower cost, and lets the major industry players provide services to smaller firms at a competitive price. Get Down to Basics As companies return to a back-to-basics approach and shed operations that do little to enhance the bottom line, they're looking to offload non-core business functions to third parties who can do it better, faster, and cheaper. Although many company systems have become so tightly coupled to the core business process that they can't be removed without a major disruption to the business, other operations, such as external interfaces, are great candidates for outsourcing. By looking at the areas of a business that carry little risk (for example, customer call centers) and/or have loosely-coupled functions (for example, company payroll and benefit administration), companies can save billions of dollars. As companies focus on cost-saving measures and leverage outside systems, they open up tightly integrated enterprise resource planning (ERP) and customer relationship management (CRM) systems and supply chain applications. Web services will drive this type of restructuring forward. Predicting the Future of Web Services (Continued) SAP's MySAP.com e-business platform is a prime example. The MySAP.com platform is based on a service-oriented architecture (SOA), which enables enterprise-scale Web services use. The platform exposes SAP's business-process solutions through Web services, which allows the gateway to extend business processes and services beyond business boundaries. Opening these previously closed systems not only eases internal integration issues, but it also promotes external collaboration and enables organizations to offload non-core business functions that target specific areas of the business, such as order fulfillment and inventory control. This model provides the basic template for the complete virtual corporation. You can view each business function as a component in a larger context, supported through loosely coupled business objects. This allows for rapid changes in supplier relationships, product/market alignment, and pricing structures. The virtual corporation can purchase functionality on the open market, regardless of borders and high-cost barriers to entry. The platform will also provide a new business model for companies that want to target specific areas of the business. These new businesses might be sole providers of a service or act as brokers. Web services take on an intricate part of every business function. For this to work, Web services will rely on Business Process Management (BPM) tools that can orchestrate the process flows and coordinate the execution of a collection of Web services within the context of a business transaction. Because orchestration and coordination are integral to most enterprise application integration (EAI) middleware, it's natural for the EAI middleware vendors to extend their offerings to embrace Web services. The combination of solid BPM tools and solid Web services standards and frameworks will complete the puzzle necessary to offload non-core business functionality. Provide Business Process Integration With the advent of a SOA, many middleware providers include Web services as part of their product offerings. Companies such as Vitria expose their integration solutions as Web services to reduce the complexity of integrating internal applications and to extend these services to partners and industries external to the business (see Resources). Exposing these processes as Web services eliminates the labor-intensive and costly use of proprietary interfaces. In addition, Web services provide the foundation for BPM necessary to change business processes quickly and easily to meet the evolving needs of the market, partners, and other applications. It's important to note that Web services—with future layers of orchestration, collaboration, and workflow standards—will be only a part of a larger picture of distributed services. You can expect today's middleware and application development tool vendors to extend Web services to provide functionality and ease of use that will map business processes to application functions in a seamless fashion, regardless of platform, language, or device. Predicting the Future of Web Services (Continued) ADVERTISEMENT Integrated environments such as Microsoft's Visual Studio .NET already provide a core framework to leverage, create, and consume Web services in a seamless fashion. Other integrated environments such as IBM's WebSphere are extending their J2EE environments to incorporate Web services into an easy-to-use development platform. Both the .NET and J2EE camps will enhance their Web services products to further embrace BPM. In the not-too-distant future, it will be possible to discover, bind, and execute Web services dynamically, on the fly, and to coordinate the process flow through one integrated environment. This will allow for external Web services to be widely adopted. Because business relationships are contractual by nature, the need for service level agreements (SLAs), onfidentiality/security, and alternative suppliers is a must for any business providing or consuming Web services. As the number of businesses publishing Web service grows, the industry will gravitate toward a brokerage model. Brokers will provide service alternatives to guarantee 24/7 availability and help monitor/meter Web services. They will also validate service providers and provide one-stop shopping for Web services. Brokers will align themselves with specific vertical industries and become a defining force in future standards. This will consolidate industry specific providers over time, which will feed an ever-increasing field of virtual corporations. Centralize Web Services Web services will greatly expand the availability of centralized real-time services, regardless of platform or device. They'll not only expose functionality, but Web services will carry self-describing information to enable any device to consume or redistribute a service. Organizations have tried for years to provide a centralized view of the their individual services. The need to see an organization's information in real time and to make accurate business decisions based on that information is essential to future business planning. A central repository of Web services can provide the realtime view into the disparate systems throughout the organization. This doesn't alleviate the need for a data warehouse, nor does it work without a solid middleware infrastructure that supports BPM. Centralizing process in real time through the advent of Web services should incorporate a robust transformation product that can normalize responses from multiple systems and present specific data back to requesting services in real time in the correct format. Transformation products can also be used to feed BPM tools to complete a well-rounded, realtime, centralized Web services repository. Ascential Software's DataStage product combined with BPM tools from Vitria, WebMethods, IBM, Microsoft, and so on, will provide a firm base to create a centralized repository that's essential to the future of Web services (see Resources). Predicting the Future of Web Services (Continued) Using Web services to centralize processes is a complex endeavor. The tools you select should provide graphical modeling of the business processes and transparently generate the code necessary to communicate with the Web services according to rules embedded in the model. The industry is moving towards XML Language (XLang) as one of several business process languages to become part of the Web services stack, along with Web Services Flow Language (WSFL) as submitted by IBM. To remain competitive, BPM tool vendors will need to accept a standard business process language so their products can be interchangeable at the business service level. This will allow businesses to select the best BTM tool for their specific environment needs. Web services outside the firewall are on the verge of a great leap forward. That leap will take place by way of new integrated development environments combined with Web services intermediaries (brokers), which will provide the assurances and strong relationships necessary to promote a truly shared services architecture that crosses business boundaries. If you want to get started now, you can combine transformation and BPM tools with Web services integrated development environments from Microsoft, IBM, Oracle, Sun, and BEA to build a basic framework from which to grow on. It will be some time before the Web services stack settles on workflow, collaboration, and orchestration standards. The strong BPM products available currently might be all you need for a long time to make Web services outside the firewall the true Holy Grail of a SOA. About the Author Robert Wegener is the director of solutions for RCG IT's Web services, a provider of IT professional services. He has more than 20 years of information and business engineering experience in operations, customer service, transportation, finance, product development, telecommunications, and information systems. E-mail Robert at dotnet@fawcette.com 中文译文 预测web服务的未来:对于企业中的web服务,解读四大商业驱动力如何打造其发展空间 by Robert Wegener Tech Ed 2003 Issue 在对“web 服务”这个名词含义进行界定的过程中,我们虽然很难预料应该为其准备些什么,但是决不能忽视商业驱动力对于未来技术的重大影响。在本文中,笔者的假定是对于这些驱动力,在适当的位置上有必要的标准,市场上主要的竞争者均对其提供支持,并在此假定的基础上,来探讨这些驱动力的作用(见图1)。主要的驱动力包括:不断增长的市场份额,卸载一些非核心商业功能的趋势,快速简易的联合工艺和良好的适应性,以及集成化,跨平台的服务实时性。同时,在拓展企业业务方面,web 服务也是防火墙内外的有力工具。因此,如前所述,这些驱动力已经具备了推动web服务发展的潜质。 不断增长的市场份额是防火墙以外的最大驱动力。目前,Web能够让业务拓展到全世界的客户。企业通过把促销的链接信息放到别的网站上,用户也能去访问该企业的相关网站。不过,这种技术让客户在网站之间跳来跳去,使得他们觉得很多东西大同小异,反而会失去兴趣,不再有任何购买的行为。于是,商业网站通过增加更多的内容来解决这个问题。但是更多不意味着更好,这种情况下,往往会冲淡公司提供的核心产品的形象。 Web服务有一个最伟大的承诺,那就是能够提供“一站店”的服务。也就是说任何一个商家都可以把别人的web服务放到它自己的网站上,并提供访问相关内容的权限,这样用户就不用离开它的网站也能找到相关商品的信息。比如,有一个独立图书经销商通过整合亚马逊的web服务,使用户可以访问到亚马逊所有的库存图书详情,这样就用不着为了一个特定的标题而把用户送到亚马逊的网站上。一般说来,这样的标题在该图书经销商的网站上是可见的,而对用户却是透明的。这样的话,转销商的利益,亚马逊零售方面的份额都能得到保护和提高,用户使用web服务的经验也会得到提高。提供对终端用户透明服务的这种能力,一方面可以提高用户的购物经验,另一方面也允许在更低的成本下,一些更小的网站能为用户提供更多的服务,此外也让一些业内大老愿意在有相当竞争力的价位下,给一些小公司提供服务。 认真考虑基本要素 当前,一些公司又重新回到了要素支持的运作方法,并把对公司底线促进不大的运作分发出去,他们正在寻求把一些非核心的商业职能工作发包给第三方公司去做,这些第三方公司做起来更好,更快,也更便宜。诚然,许多公司的系统与核心的业务处理已经紧密相连,除非是对业务进行大的拆分才能将其分开,但是,其他的操作如外部的界面就特别适合外包。许多公司将注意力聚焦在一些低风险的业务领域(比如客户呼叫中心)以及一些松散的功能服务,希望能够通过外包节省数十几亿美元的开支。也正是因为这些公司把采取了成本降低的措施和系统外部的调节作用,他们才精力去开发企业资源规划(ERP)系统和客户关系管理(CRM)系统,并提供若干应用软件系列。Web服务恰恰能够把这种结构重组的工作不断推向前进。 对Web服务未来的预测(待续) SAP的MySAP.COM电子商务平台是最显著的一个例子。MySAP.COM是基于面向服务的架构(SOA),并采用了企业级的Web服务。这种平台充分利用了web服务中SAP业务处理的解决方案,并可允许网关去扩展若干超越业务边界的业务处理和服务。开放以前封闭式的系统不仅可以简化内部一些涉及到系统整体性的问题,还可以提升外部的协作性,使得相关组织卸载掉一些非核心的业务功能,这些非核心的业务功能主要集中在一些特定的业务领域,诸如完成订单,库存控制等。 此种模型为完全的虚拟公司提供了基本的模板。你会发现每个业务功能就像是一片大文章中的小段落,它们通过松散连接的业务对象来获取支持,还能适应供应商关系,产品/市场体系,报价结构的快速变化。在开放的市场上,虚拟的公司可以购买功能模块,而不用考虑任何准入的边界和高成本的壁垒。 对于那些想把目标锁定在特定业务领域的公司来说,这个平台也为他们提供了一个新的业务模型。这些新业务可能会是某项服务的唯一提供者,也有可能充当经纪人的角色。为此,在业务交易的范围内,Web服务将要依靠业务处理管理(BPM)工具,该工具能够协调处理流程,整理Web服务集合的运行。由于对于大多数企业应用集成(EAI)的中间件来说,协调和整理是密不可分的,所以那些EAI中间件的卖家把他们提供的商品范围进行扩展以接纳Web服务,也就成了顺理成章的事了。只不过,这样一来,可靠的BPM工具,可靠的Web服务标准和构架,它们之间的融合会对卸载非核心商业功能的必要性提出挑战。 提供业务处理整合方案 随着SOA的到来,许多中间件的供应商都把Web服务作为自己商品提供的一部分。一些公司(比如Vitria)都把Web服务作为系统整合的解决方案,并以此来降低内部应用整合的复杂度,也以此来把服务扩展到业务以外的合作伙伴和行业中去(见Resources)。 以web服务的方式来展现这些处理过程,可以消除密集型劳动和高效利用私人接口。此外,为了满足市场,合作伙伴,和其他应用不断发展变化的需求,各公司势必也要迅速简洁的改变业务处理流程以便及时跟进,而Web服务恰恰可以为此提供BPM的基础。 注意到以下这点亦非常重要,那就是:即便是将来采用了协调、合作以及工作流程标准的若干层次,在分布式服务这张大的蓝图中,Web服务也只是其中一个小小的部分。不过,值得期待的是,今天的中间件和应用开发工具的卖家一定会把web服务加以扩展,使之在功能性和应用的简易性方面大有可为,这样就可以把业务处理流程无缝接入到应用功能上,正真做到跨平台,跨语言,跨设备。 对Web服务未来的预测(待续) 一些诸如Microsoft's Visual Studio .NET的集成开发环境已经可以提供核心的架构,此种架构可以无缝接入的方式来协调、创建或是消费Web服务。其他诸如IBM的WebSphere的集成开发环境也正在扩展他们的J2EE开发环境,以便能够把Web服务整合到某个简单易用的开发平台上去。预计.NET阵营和J2EE阵营将来都会提升各自的Web服务产品,争取能进一步的接纳BPM。在不久的将来,人们可能发现,绑定,动态运行web服务,或是挂起,抑或是通过某个集成的开发环境调整处理流程,让外部的web服务在一个非常广泛的领域中被采用。由于许多业务关系是约定俗成的,因而就需要有相关的服务水平协议(SLAs),相关的保密安全协议以及可供选择的供应商,而这些需求又是任何业务提供和消费web服务必不可少的。 随着业务上发布的web服务数量的不断增加,整个行业将被吸引到往经纪人业务模型这个方向发展。众多经纪人会提供若干可供选择的服务,并会保证这些服务是全天候的,还能帮忙监控评估相关的web服务。这些经纪人也将负责验证服务提供者的有效性,还将提供基于Web服务的“一站店”,他们还会与一些行业规则看齐,并会成为未来标准的制定者之一。这样一来,对于那些业内特定的供应商来说,他们地位的巩固性就会与时俱进,进而又能培育出虚拟公司不断增长的应用领域。 Web服务的集中性 对于集中式实时服务来说,Web服务以跨平台或跨设备的方式极大的扩展了它们的可用性。除了展示相关的功能以外,web服务还能携带自我描述的信息,可以让任何一个设备消费或是重新分配某项服务。 数年来,各种组织都试图把它们单独的服务集中起来。这样就需要实时看到某个组织的信息,并基于此信息做出准确的业务抉择,而这些优势又是将来业务规划必不可少的。对于贯穿整个组织内各个不同的系统,Web 服务的中心库可以把实时的视图放置于其中,降低了对数据仓库的需求,还可以兼容于那些支持BPM的底层中间件。 由Web服务的出现而引发的实时性服务集成处理,应当有一个健壮的转换产品,该产品可以规范化来自多系统的响应,并能以正确的格式实时的把特定的数据送回以请求服务。这种转换产品也可以用来培育开发BPM工具,以此来提升web服务中心库的完备性,实时性和集成性。Ascentia软件公司的DataStage产品,结合了来自Vitria, WebMethods, IBM,微软等公司的BPM工具,提供了集成中心库的坚实基础,并对web服务的将来发展是起到至关重要的作用。(见Resources) 对Web服务未来的预测(待续) 利用Web服务来集成处理流程是一件很复杂的工作。你可以选择相关工具来对业务处理流程进行图形化建模,并透明的生成必要代码,根据模型内部嵌入的规则,和web服务进行沟通。目前整个行业正在向XML语言转移,该语言是几种业务处理语言之一,也是Web服务堆栈的一部分,和Web服务流程语言(WSFL)一起都是由IBM提交的。为了保持市场竞争力,BPM工具的卖家可能需要接纳一种标准的业务处理语言,这样,他们的产品就能在业务服务的层面上做到相互之间可以进行修改。另外,还能为一些业务流程选择到最好的BTM工具,满足特定环境的需求。 防火墙外的Web服务目前正面临着向前巨大跃进的大好机遇。这种跃进是由新的集成式开发环境结合web服务经纪人来引发的,并为推动跨业务边界的真正共享式服务的发展提供强有力的保证和必要的相互关系。 如果你想现在就开始,你就应该用微软、IBM、Oracle、Sun和BEA 的Web服务集成开发环境来把转换产品和BPM工具相结合,以此来构造一个可扩展的基础性架构。当然,要把Web服务的堆栈放到工作流程,合作协调的标准之上,仍尚需时日。为了使防火墙外的web服务成为真正的SOA圣杯,在相当长的时间内,你所需要的仍然是目前强大的BPM产品。 关于作者 Robert Wegener先生是RCT IT 公司Web服务解决方案的主管,该公司是一家IT专业服务的供应商。在信息和业务工程方面,比如操作,客户服务,运输,财务,产品开发,电信和信息系统等方面,Robert Wegener先生有着20多年的丰富经验。他的电子邮件:dotnet@fawcette.com.

继续阅读《预测web服务的未来》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(210) | 评论 (0)编辑 收藏

unit CPower; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormPaint(Sender: TObject); private { Private declarations } procedure WMPowerBroadcast(var message: TMessage); message WM_POWERBROADCA ST; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} { TForm1 } procedure TForm1.WMPowerBroadcast(var message: TMessage); const SkipNextPowerMsg:boolean=True; begin if SkipNextPowerMsg then begin SetForegroundWindow(Self.Handle); if Application.MessageBox('是否关闭系统?','警告',MB_OKCANCEL + MB_DEFBU TTON2)<>IDOK then begin message.Result := BROADCAST_QUERY_DENY; SkipNextPowerMsg:=not SkipNextPowerMsg; end else Close; end else SkipNextPowerMsg:=not SkipNextPowerMsg; end; procedure TForm1.FormPaint(Sender: TObject); begin Self.Visible:=False; end; end.

继续阅读《如何屏蔽一个按键》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(300) | 评论 (0)编辑 收藏

unit UntCall; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,tAPI, Buttons, ComCtrls, ExtCtrls, DB, ADODB,StrUtils, Menus,MMSystem, DBTables, Mask; Const Handle_Use_Default=0; type TFrm_Call = class(TForm) Label1: TLabel; edt_ComPort: TEdit; Label2: TLabel; edt_phone: TEdit; cmd_Start: TBitBtn; Label3: TLabel; edt_Time: TEdit; Label4: TLabel; TrackBar1: TTrackBar; cmd_Stop: TBitBtn; Timer_Run: TTimer; ListBox1: TListBox; Timer_ShutDown: TTimer; ADOQuery_A: TADOQuery; Label5: TLabel; edt_SoundTime: TEdit; PopupMenu1: TPopupMenu; N1: TMenuItem; N2: TMenuItem; SaveDialog1: TSaveDialog; MainMenu1: TMainMenu; GroupBox1: TGroupBox; RadioButton_AT: TRadioButton; RadioButton_tAPI: TRadioButton; Timer_Play: TTimer; AdoQuery_W: TQuery; edt_WaveFile: TEdit; cmd_GetWaveFile: TSpeedButton; OpenDialog1: TOpenDialog; cmd_Firm: TBitBtn; chk_ShutDown: TCheckBox; edt_ShutDownTime: TMaskEdit; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); procedure cmd_StartClick(Sender: TObject); procedure cmd_StopClick(Sender: TObject); procedure Timer_RunTimer(Sender: TObject); procedure N1Click(Sender: TObject); procedure N2Click(Sender: TObject); procedure Timer_PlayTimer(Sender: TObject); procedure cmd_GetWaveFileClick(Sender: TObject); procedure cmd_FirmClick(Sender: TObject); procedure Timer_ShutDownTimer(Sender: TObject); private fPhone:string; fName:string; fCallStatus:Cardinal; fWaveFile:string; public Function ReadInfoFromDataLoop(var sPhone,sName:string):Boolean; Function APIDialTest:Boolean; //tapi拨号测试 Function APIDialPrepare:Boolean; //拨号准备线路 Function APIDial(const sPhone:string=''):Boolean; //API拨号MakeCall Function APIGetCallStatus(var dwState:Cardinal):Boolean; //API的获取当前拨号状态 Function APIStartCall(const sPhoneNumber:string=''):Boolean; //整体拨号 Function APIStopCall(const nTimeOut:Cardinal=50):Boolean; //停止拨号 Function ATInitlizeModem:Boolean; //AT初始化拨号 Function ATCall(const sPhone:string=''):Boolean; //AT的拨号程序 Function DoAtCommand(const sATCommand:string='';hFileHandle:tHandle=Handle_Use_Default):Boolean; Procedure ShowModemStatusInfo; //显示MODEM状态信息 Procedure ShowInfo(const sMsg:string='';lShowTime:Boolean=True;lMessageBox:Boolean=False); Function BuildRegistInfo(var sMachine,sKey:string):Boolean; Function ReadConfig(sKey:string;vValue:Variant):Boolean; End; var Frm_Call: TFrm_Call; LineApp:hLineApp; //tAPI句柄 Line:HLine; //线路句柄 LineID:dWord; //GetLineID的返回 Call:HCall; //呼叫句柄 CallParams:tLineCallParams; //线路呼叫参数 nDevs,APIVersion,ErrorCode:dWord; //线路设备数,版本号,错误代码 AddressID:Cardinal; //地址号 extID:tLineExtensionID; //tAPI扩展版本号 LineIcon:HIcon; //线路设备图标 hCommFile:tHandle; //使用AT时候的文件句柄 ModemStatus:dWord; //Modem状态随时保存进来 NumberWritten:dWord; //写入串口的字符数量 WaveOut:hWaveOut; //声音输出 WaveFormat:pWaveFormatEX; //PCMWAVEFORMAT; //声音类型 WaveHead:WaveHDR; //声音头 xWaveDevice:tHandle; //声音输出设备 xData:hGlobal; //数据保存 pData:^Byte; //真正的数据保存区,指针 SndDataSize:dWord; //播放的数据缓冲区的大小 SndPlayTime:MMTime; //播放的时间信息 SndWaveFile:string; //要播放的声音文件 PlaySignal:Boolean; //正在播放的标志 xHandle:dWord; //保存句柄 xInstance:Cardinal; //保存自身 DialRunType:Cardinal; //拨号类别:1=循环拨号,2=固定拨号 Procedure LineCallBack(hDevice,dwMsg,dwCallBackInstance, dwParam1,dwParam2,dwParam3:LongInt);stdCall; Procedure WaveOutProc(hwo:HWAVEOUT; uMsg,dwInstance,dwParam1,dwParam2:DWORD);StdCall; Function OpenWaveFile(sFile:string):dWord; //打开文件准备 Function PlayWaveFile(hHandle:Hwnd):dWord; //播放声音文件 Function StopPlay:Boolean; //停止播放文件,但没有关闭 Function ClosePlay:Boolean; //最终关闭播放 Function Interchange(hpchPos1, hpchPos2 : PChar; wLength : word):Boolean; //数据区对调 implementation Uses UntMDI; {$R *.dfm} //============================================================================// //---------------获取系统注册信息,写入sMachine/sKey-----------------// Function tFrm_Call.BuildRegistInfo(var sMachine,sKey:string):Boolean; var xMachine,xKey:String; Begin Result:=False; End; //-------------------读取系统设置-----------------------// Function tFrm_Call.ReadConfig(sKey:string;vValue:Variant):Boolean; Begin Result:=False; End; //---------------------拨号---------------------// Function tFrm_Call.APIStartCall(const sPhoneNumber:string=''):Boolean; //拨号 Begin Result:=False; if trim(sPhoneNumber)='' then exit; if not APIDialTest then exit; if not APIDialPrepare then exit; if not APIDial(sPhoneNumber) then exit; Result:=True; End; //--------------------停止拨号-----------------// Function tFrm_Call.APIStopCall(const nTimeOut:Cardinal=50):Boolean; //停止拨号 Begin Result:=False; LineClose(Line); LineShutDown(LineApp); Result:=True; End; //----------获取拨号线路设备ID----------------// Function GetWaveDeviceID:dWord; var nState,nNeedSize,nLen:dWord; xVarString:pVarString; xValue:pChar; Begin Result:=0; nLen:=8; //用来保存ID的长度 nNeedSize:=SizeOf(varString)+nLen; While True do begin //因为缓冲区可能小 GetMem(xVarString,nNeedSize); //分配内存区,注意:此处需为VarString而不是他的指针!! xVarString.dwTotalSize:=nNeedSize; //初始化变量 StringFormat_Binary nState:=LineGetID(Line,AddressID,Call,LINECALLSELECT_Call,xVarString,'wave/out'); //成功返回0;2147483725 = STRUCTURETOOSMALL if xVarString.dwTotalSize>=xVarString.dwNeededSize then Break; //重新分配内存区 if (nState<>LINEERR_STRUCTURETOOSMALL) and (nState<>0) then Exit; nNeedSize:=xVarString.dwNeededSize+nLen; FreeMem(xVarString); End; //dwWaveDev = (DWORD) * ((DWORD *) ((LPSTR)vs + vs->dwStringOffset) ); //Result:=PHandle(LpStr(xVarString)[xVarString.dwStringOffset])^; Try GetMem(xValue,xVarString^.dwStringSize); Move( pChar(xVarString)[xVarString^.dwStringOffset],xValue^,xVarString^.dwStringSize); //xVarString^.dwStringOffset Result:=dWord(xValue^); Finally FreeMem(xValue); FreeMem(xVarString); End; { Inc(xVarString,xVarString^.dwStringOffset); Result:=(pDWord(xVarString))^; Dec(xVarString,xVarString^.dwStringOffset); } {About Params named 'DeviceClass' of LineGetID: If you want to play audio over the phone line, you should specify "wave/out"; if you want to record audio, use "wave/in".} End; //-----------------打开声音文件并准备之-----------------------// Function OpenWaveFile(sFile:string):dWord; Type _PInfo=Record //播放格式的结构 FileName:string; FCC:FourCC; End; Var xMMIO:hMMIO; xMMIOInfo:pMMIOInfo; pInfo,cInfo:MMCKINFO; //实例化变量 nValue:dWord; Pt1,Pt2:pChar; Label Error_Exit; Begin Result:=0; pData:=0; xData:=0; if not FileExists(sFile) then exit; //分配内存区 GetMem(xMMIOInfo,sizeof(tMMIOInfo)); if WaveFormat=nil then GetMem(WaveFormat,sizeof(tWaveFormatEX)); //打开文件 xMmio:=mmioOpen(pChar(sFile),0,MMIO_READ); //xMMIOInfo Nil if xMMIO=NULL then GOTO Error_Exit; //成功返回句柄,失败返回NULL //查找WAVE格式的父块Wave pInfo.fccType:=mmioStringToFourCC('wave',mmio_ToUpper); if mmioDescend(xMmio,@pinfo,Nil,MMIO_FindRiff)<>MMSYSERR_NOERROR then goto Error_Exit; //进入FMT块 cInfo.cksize:=16; cInfo.ckid:=mmioStringToFourCC('fmt ',0); //此处注意大小写! mmioFOURCC if mmioDescend(xMMIO,@cInfo,@pInfo,MMIO_FindChunk)<>MMSysErr_NoError then goto Error_Exit; //MMIOERR_CHUNKNOTFOUND //读取文件格式 nValue:=cInfo.cksize; //文件格式大小 GetMem(WaveFormat,nValue); //重新分配内存 if (mmioRead(xMMIO,pChar(WaveFormat),nValue)<>nValue) then goto Error_Exit;//读取文件头格式的字节数填充,到了文件底部或字节数不足返回0,错误返回-1,正确返回字节数 if WaveFormat^.wFormatTag<>Wave_Format_PCM then goto Error_Exit; if mmioAscend(xMMIO,@cInfo,0)<>MMSysErr_NoError then goto Error_Exit; //跳 //查找DATA数据块 cInfo.ckid:=mmioStringToFourCC('data',0); if mmioDescend(xMMIO,@cInfo,@pInfo,mmio_FindChunk)<>MMSysErr_NoError then goto Error_Exit; sndDataSize:=cInfo.cksize; //数据区大小 //下面将读取数据 xData:=GlobalAlloc(GMEM_MOVEABLE + GMEM_SHARE,SndDataSize); //分配内容并设置其属性 pData:=GlobalLock(xData); //锁定内存区,并返回地址 if mmioRead(xMMIO,pChar(pData),SndDataSize)<>SndDataSize then goto Error_Exit; {//特殊情况的处理:数据区块前后对调 nValue:=WaveFormat^.nBlockAlign; Pt1:=pChar(pData); Pt2:=pChar(pData) + SndDataSize - 1; While Pt1 < Pt2 do begin InterChange(Pt1,Pt2,nValue); //数据交换 Inc (Pt1, nValue); //+ Dec (Pt2, nValue) //- end; } //设置播放的声音头信息,里边包含需要播放的缓冲区地址、长度等 WaveHead.lpData:=pChar(pData); //数据源指针 WaveHead.dwBufferLength:=sndDataSize; //数据缓冲区大小 WaveHead.dwFlags:=0; WaveHead.dwLoops:=3; WaveHead.dwUser:=0; //完成了,关闭MMIO mmioClose(xMMIO,mmio_FHOpen); //清理内存区 FreeMem(xMMIOInfo); Result:=SndDataSize; //成功返回字节数 Exit; Error_Exit: ErrorCode:=$FFFF; //设置错误标志 FreeMem(xMMIOInfo); FreeMem(WaveFormat); if pData<>nil then LocalUnLock(xData); //xData if xData<>Null then GlobalFree(xData); //释放获取的全局锁定内存 End; //-------------播放声音文件------------------------------------// Function PlayWaveFile(hHandle:Hwnd):dWord; var nValue:dWord; label Error_Exit; Begin Result:=0; if WaveFormat=Nil then GetMem(WaveFormat,sizeof(tWaveFormatEX)); //分配内存区 //检测是否能够播放,此处phWaveOut可以是Null,设备ID可以是Wave_Mapper nValue:=WaveOutOpen(0,xWaveDevice,WaveFormat,0,0,Wave_Format_Query); //xWaveDevice,格式查询LineMapper IF nValue<>MmSysErr_NoError then goto Error_Exit; //mmSysErr_NoError=0 //设置回调处理函数&窗口并测试 nValue:=WaveOutOpen(@WaveOut,xWaveDevice,WaveFormat,Cardinal(@WaveOutProc),xInstance,CallBack_Function); if nValue<>mmSysErr_NoError then Exit; //通知输出设备准备好数据结构头 nValue:=WaveOutPrepareHeader(WaveOut,pWaveHDR(@WaveHead),sizeof(WaveHead)); if nValue<>mmSysErr_NoError then exit; //最终写入输出设备 nValue:=WaveOutWrite(WaveOut,@WaveHead,sizeof(WaveHDR)); if nValue<>mmSysErr_NoError then exit; PlaySignal:=True; Result:=1; Error_Exit: if WaveFormat<>Nil then FreeMem(WaveFormat); if Result=0 then Messagebox(xHandle,'[PlayWaveFile]播放文件失败,可能格式错误、线路错误等。请检查!','播放错误',32); if Result=0 then setLastError(11255); End; //-------------------停止播放,但没关闭------------------------// Function StopPlay:Boolean; Begin Result:=( WaveOutReset(WaveOut)<>mmSysErr_NoError ); End; //------------------全部停止,释放资源-------------------------// Function ClosePlay:Boolean; Begin Result:=False; //如果没有释放,则此处释放之 if WaveOut<>Null then Try WaveOutReset(WaveOut); //重置,释放 WaveOutClose(WaveOut); //关闭,包括文件 WaveOutUnPrepareHeader(WaveOut,@WaveHead,sizeof(WaveHDR)); Except Exit; End; //释放锁定的内存区 GlobalUnLock(xData); //撤销内存锁定 GlobalFree(xData); //释放全局内存 //结束 Result:=True; End; //----------------声音处理的回调函数---------------------------// Procedure WaveOutProc(hwo:HWAVEOUT; uMsg,dwInstance,dwParam1,dwParam2:dWORD);StdCall; Begin Case uMsg of WOM_DONE: //播放完毕了,WaveOutWrite函数触发 Begin PlaySignal:=True; ClosePlay; //停止播放 End; WOM_CLOSE: //当WaveOutClose函数完毕时触发 Begin PlaySignal:=False; End; WOM_Open: //WaveOutOpen函数 Begin PlaySignal:=True; End; Else Begin End; End; End; //----------------------回调处理的主函数----------------------------------// {tAPI异步呼叫返回处理函数,因为窗口隐藏,所以这里处理返回的消息} Procedure LineCallBack(hDevice,dwMsg,dwCallBackInstance, dwParam1,dwParam2,dwParam3:LongInt);stdCall; var lCall:HCall; Buffer:pChar; begin With untCall.Frm_Call do begin if dwParam2<0 then Begin ShowInfo('LineCallBack:呼叫响应错误!'); Exit; END; //-----根据dwMessage的消息类别判断 Case dwMsg of Line_Reply: //LineMakeCall结果,Relay:答复 Begin //ShowMessage('Line_Reply!!!拨叫成功,写入呼叫句柄Call成功'); End; Line_CallState: //返回呼叫状态时的处理 Begin lCall:=hCall(hDevice); //类型转换 Case dwParam1 of //类型值 LineCallState_IDLE: //呼叫无效 Begin ShowInfo('呼叫无效,断开'); if Call<>0 then LineDealLocateCall(lCall); //呼叫无效,断开 End; LineCallState_Connected: //连接成功 Begin ShowInfo('LineCallState_Connected!'); //获取线路设备ID xWaveDevice:=GetWaveDeviceID(); if xWaveDevice=0 then exit; //播放声音 if OpenWaveFile(SndWaveFile)=0 then exit; PlayWaveFile(xHandle); End; Line_MonitorDigits: //接收用户按键 Begin //ShowMessage('Line_MonitorDigits'); ShowInfo('接收用户按键。。。。。。'); End; LineCallState_Accepted: //用户接收了连接:此处不对! Begin //ShowMessage('LineCallState_Accepted'); //ShowInfo('用户接收了连接!'); End; LineCallState_Offering: //对方要求应答 Begin //ShowMessage('LineCallState_Offering'); End; LINECALLSTATE_BUSY: //占线忙音 Begin //ShowMessage('LineCallState_Busy'); ShowInfo('占线。。。。。。'); End; LineCallState_Proceeding: //正常处理的 Begin //ShowMessage('LineCallState_Procedding'); ShowInfo('正在处理Proceeding......'); End; LineCallState_DialTone: //检测到拨号音 Begin //ShowMessage('LineCallState_DialTone'); ShowInfo('检测到拨号音'); End; LineCallState_Dialing: //正在拨号中 Begin //ShowMessage('LineCallState_Dialing'); End; LineCallState_DisConnected: //断开连接 Begin //ShowMessage('LineCallState_Disconnected'); PlaySignal:=False; End; Else END; End; Line_LineDevState: Begin Case dwParam1 of LineDevState_Connected: //连接完毕 Begin //ShowMessage('线路设备连接成功!LineDevState_Connected'); ShowInfo('线路设备连接成功!'); End; LINEDEVSTATE_RINGING: //正在拨号响声 Begin //ShowMessage('线路设备正在响铃LineDevState_Ring'); ShowInfo('正在响铃Ring'); End; LINEDEVSTATE_DISCONNECTED: //断开连接 Begin //ShowMessage('线路设备断开!LineDevState_DisConnected'); End; Else Begin End; End; End; End; end; End; //--------------------TAPI拨号准备:版本检查等--------------------------// Function tFrm_Call.APIDialTest:Boolean; Begin Result:=False; If LineInitialize(@LineApp,HInstance,@LineCallBack,'海宏拨号程序',nDevs)<0 then //初始化线路 ShowInfo('线路初始化失败,请检查线路',True,True) Else If nDevs=0 then //没有TAPI线路设备 Begin LineShutDown(LineApp); LineApp:=0; End Else //协商TAPI版本号 1.4~3.0 If LineNegotiateAPIVersion(LineApp,0,$00010004,$00030000, APIVersion,extID)>=0 then Result:=True //成功 Else Begin ShowInfo('TAPI版本不兼容!1.4~3.0',True,True); LineShutDown(LineApp); LineApp:=0; End; End; //---------------------tAPI拨号准备:打开线路等---------------------------// function tFrm_Call.APIDialPrepare:Boolean; Begin Result:=False; with UntCall.CallParams do //设置呼叫参数 Begin callParams.dwTotalSize:=sizeof(CallParams); //大小 callParams.dwBearerMode:=LineBearerMode_Voice; //语音承载模式 CallParams.dwMediaMode:=LineMediaMode_InteractiveVoice; //媒体模式为交换式语音 CallParams.dwNoAnswerTimeout:=StrToIntDef(self.edt_Time.Text,20000); //没有应答的等待时间 //CallParams.dwAddressMode:=LINEADDRESSMODE_DIALABLEADDR; //任何可以拨号的地址,LineOpen拨号不能用LINEADDRESSMODE_AddressID End; if True then Begin //打开线路 //应答方需要:用LINECALLPRIVILEGE_MONITOR+LINECALLPRIVILEGE_OWNER //呼叫方需要:LineCallPrivilege_None ErrorCode:=LineOpen(LineApp,LineMapper,@Line,APIVersion,0,0, LineCallPrivilege_None,LineMediaMode_InteractiveVoice, @CallParams); //LineMediaMode_InteractiveVoice / LINEMEDIAMODE_AUTOMATEDVOICE if ErrorCode<0 then ShowInfo('线路不能打开!',True,True) else Begin //LineConfigDialog(0,self.Handle,Nil); //线路设备属性对话框 LineGetIcon(0,'tapi/line',@LineIcon); //线路图标句柄,可辅给tICON.Handle End; End; Result:=True; End; //--------------------------拨号-----------------------------// Function tFrm_Call.APIDial(const sPhone:string=''):Boolean; Begin Result:=False; if sPhone='' then exit; ErrorCode:=LineMakeCall(Line,@call,pchar(sPhone),0,@CallParams); if ErrorCode<0 then showmessage('呼叫失败!') else begin //拨通,提示摘机通话 //Sleep(StrToIntDef(self.edt_Time.Text,12500) ); ErrorCode:=LineGetAddressID(Line,AddressID,CallParams.dwAddressMode,pChar(sPhone),Length(sPhone)); Result:=True; End; End; //-------------获取API拨号的状态---------------------------// Function tFrm_Call.APIGetCallStatus(var dwState:Cardinal):Boolean; //API的获取当前拨号状态 Var CallStatus:pLineCallStatus; nValue,nNeedSize:Cardinal; Begin Result:=False; if Call=0 then exit; nNeedSize:=sizeof(tLineCallStatus); While True Do Begin GetMem(CallStatus,nNeedSize); CallStatus^.dwTotalSize:=nNeedSize; nValue:=LineGetCallStatus(Call,CallStatus); if (nValue<>0) and (nValue<>LINEERR_STRUCTURETOOSMALL) then Exit; if CallStatus^.dwNeededSize <= CallStatus^.dwTotalSize then Break; nNeedSize:=CallStatus^.dwNeededSize; FreeMem(CallStatus); End; nValue:=CallStatus^.dwCallState; //状态 dwState:=nValue; FreeMem(CallStatus); Result:=True; End; //---------------从数据库循环读取信息,写入fPhone/fName---------------------// Function tFrm_Call.ReadInfoFromDataLoop(var sPhone,sName:string):Boolean; //传址 var xName,xPhone:string; Begin Result:=False; xPhone:=''; xName:=''; if DialRunType=2 then begin sPhone:=edt_Phone.Text; sName:='固定拨号'; Result:=True; Exit; End; If AdoQuery_W.Eof then Try AdoQuery_W.First; Except ShowInfo('移动数据库记录错误,终止'); Exit; End; If not AdoQuery_W.Eof then Try if AdoQuery_W.FieldValues['sPhone']<>NULL then xPhone:=Trim(AdoQuery_W.FieldValues['sPhone']); if AdoQuery_W.FieldValues['sName']<>NULL then xName:=Trim(AdoQuery_W.FieldValues['sName']); ShowInfo('读取数据:[名称='+xName+'];[电话='+xPhone+']'); sPhone:=xPhone; sName:=xName; AdoQuery_W.Next; //数据库记录下移 Except ShowInfo('提取数据库电话、名称数据失败!'); Exit; End; fName:=xName; fPhone:=xPhone; //同时记录下来 Result:=True; End; //--------------------------数据区交换------------------------------// Function Interchange(hpchPos1, hpchPos2 : PChar; wLength : word):Boolean; Var wPlace : word; bTemp : char; Begin Result:=False; for wPlace := 0 to wLength - 1 do begin bTemp := hpchPos1[wPlace]; hpchPos1[wPlace] := hpchPos2[wPlace]; hpchPos2[wPlace] := bTemp End; Result:=True; End; //----------------------显示MODEM状态信息---------------------------// Procedure tFrm_Call.ShowModemStatusInfo; var sInfo:string; begin sInfo:=''; if hCommFile=Invalid_Handle_Value then exit; if ModemStatus and MS_CTS_ON <>0 then sInfo:=sInfo+'CTS[清理待发送] '; if ModemStatus and MS_DSR_On <>0 then sInfo:=sInfo+'DSR[数据准备OK] '; if ModemStatus and MS_Ring_On<>0 then sInfo:=sInfo+'RING[响铃...] '; if ModemStatus and MS_RLSD_ON<>0 then sInfo:=sInfo+'RLSD[检测到接收信号]'; if sInfo<>'' then ShowInfo(sInfo); End; //----------------------------Close-------------------------------------------// procedure TFrm_Call.FormClose(Sender: TObject; var Action: TCloseAction); begin action:=CaFree; if PlaySignal then ClosePlay; if hCommFile<>Invalid_Handle_Value then Try CloseHandle(hCommFile); if WaveFormat<>Nil then FreeMem(WaveFormat,sizeof(WaveFormat)); Except End; if LineApp<>0 then Try LineShutDown(LineApp); Except End; end; //----------------------------------------------------------------------------// procedure TFrm_Call.FormCreate(Sender: TObject); var sFile:string; begin self.edt_ComPort.Text:='2'; edt_phone.Text:=''; edt_Time.Text:='22000'; ListBox1.Color:=self.Color; TrackBar1.Position:=3; edt_SoundTime.Text:='800'; edt_WaveFile.Text:=ExtractFilePath(Application.ExeName)+'GsSound.WAV'; Application.MessageBox('您使用的软件尚未注册,软件有30天试用期,请尽快联系软件供应商注册,谢谢!','软件注册',32); End; //--------------------执行AT指令函数,返回Boolean-----------------------------// Function tFrm_Call.DoAtCommand(const sATCommand:string='';hFileHandle:tHandle=Handle_Use_Default):Boolean; var fHandle:tHandle; fCommand:string; begin Result:=False; fCommand:=trim(uppercase(sAtCommand)); if (fCommand='') or (fHandle=Invalid_Handle_Value) then exit; if leftstr(fCommand,2)<>'AT' then fCommand:='AT'+fCommand; //头部AT if RightStr(fCommand,2)<>#13+#10 then fCommand:=fCommand+#13+#10; //尾部回车 if hFileHandle=Handle_Use_Default then fHandle:=hCommFile else fHandle:=hFileHandle; //写入代表串口的文件 Try Result:=WriteFile(fHandle,pChar(fCommand)^,length(fCommand),NumberWritten,Nil); Except End; //显示信息 if Result then ShowInfo('写入串口指令成功;'+'写入字节数:'+IntToStr(NumberWritten)) Else ShowInfo('写入串口指令失败!'); end; //-----------------------开始-------------------------------------------------// procedure TFrm_Call.cmd_StartClick(Sender: TObject); var CommPort,sPhone,sName:string; begin //变量、标志 DialRunType:=1; CommPort:='COM'+self.edt_ComPort.Text; hCommFile:=Invalid_Handle_Value; xWaveDevice:=0; xHandle:=self.Handle; xInstance:=Integer(self); SndPlayTime.wType:=Time_Bytes; //字节计 PlaySignal:=False; Call:=0; ErrorCode:=0; fWaveFile:=Trim(edt_WaveFile.Text); SndWaveFile:=fWaveFile; //-------------打开数据库----------------// if not AdoQuery_W.Active then //打开数据库 Try AdoQuery_W.Open; showInfo('打开数据库成功'); Except Application.MessageBox('打开数据库失败!','数据库',32); Exit; End; If AdoQuery_W.recordcount<=0 then begin ShowInfo('数据库没有数据,终止~!'); Exit; End; Timer_Run.Interval:=StrToIntDef(edt_Time.Text,15000); Timer_Play.Interval:=StrToIntDef(edt_SoundTime.Text,800); Timer_ShutDown.Enabled:=True; //--------判断拨号类别并执行-----------------------// if RadioButton_TAPI.Checked then Begin //-----TAPI拨号 if not APIDialTest then exit; //所有的初始化工作这里处理 if ReadInfoFromDataLoop(sPhone,sName) then APIStartCall(sPhone); Timer_Run.Enabled:=True; //打开循环过程 Timer_Play.Enabled:=True; //打开声音播放 End Else Begin //------AT拨号 If hCommFile=Invalid_Handle_Value then if not ATInitlizeModem() then exit; //初始化Modem Try DoAtCommand('ATL'+IntToStr(TrackBar1.Position-1)); ShowInfo('设置Modem音量'); Except End; Timer_Run.Enabled:=True; //调用主程序 Timer_Play.Enabled:=False; //关闭声音播放 End; ShowInfo('请等待,正在准备第一个拨号进程.'); end; //-----------------------停止-------------------------------------------------// procedure TFrm_Call.cmd_StopClick(Sender: TObject); begin Timer_Run.Enabled:=False; Timer_ShutDown.Enabled:=False; If RadioButton_TApi.Checked then Begin if PlaySignal then ClosePlay; APIStopCall; Timer_Play.Enabled:=False; end else Begin //---------AT----------// if hCommFile<>Invalid_Handle_Value then Try CloseHandle(hCommFile); Except ShowInfo('可忽略错误:停止关闭串口句柄失败。'); End; End; end; //--------------------------信息显示过程--------------------------------------// Procedure tFrm_Call.ShowInfo(const sMsg:string='';lShowTime:Boolean=True;lMessageBox:Boolean=False); var xMsg:string; begin if not lShowTime then xMsg:=sMsg else xMsg:=sMsg+' ['+DateTimeToStr(now)+']'; if frm_Call=Nil then exit; Frm_Call.ListBox1.Items.Add(xMsg); if lMessagebox then Messagebox(self.Handle,pchar(xMsg),pChar(Trim(application.Name)),32); end; //------------------------AT的初始化Modem-------------------------------------// Function tFrm_Call.ATInitlizeModem:Boolean; var CommPort:string; begin Result:=False; CommPort:='Com'+IntToStr( StrToIntDef(self.edt_ComPort.Text,1) ); ShowInfo('Modem线路初始化:使用串口'+CommPort); //将Com作为文件打开:名称、打开方式、共享方式、安全属性、创建属性、标志属性、取自句柄 hCommFile:=CreateFile(pChar(CommPort),Generic_Write,0,Nil,Open_Existing,File_Attribute_Normal,0); If hCommFile=Invalid_Handle_Value then ShowInfo('打开串口'+CommPort+'初始化失败!') else begin ShowInfo('打开串口'+CommPort+'成功!'); Result:=True; End; end; //---------------------AT循环拨号程序--------------------------// Function tFrm_Call.ATCall(const sPhone:string=''):Boolean; Begin Result:=False; if trim(sPhone)='' then exit; //-------显示Modem状态 if GetCommModemStatus(hCommFile,ModemStatus) then //获取Modem状态 ShowModemStatusInfo //显示MODEM状态 Else Begin ShowInfo('获取Modem状态失败!等待下次重试'); Exit; End; //----------执行AT命令断开线路----------------------------// Try DoAtCommand('ATH0'+#13+#10); ShowInfo('断开线路指令成功,准备重新拨号'); Sleep(strtointdef(edt_SoundTime.Text,800)); Except ShowInfo('断开线路指令失败,尝试继续拨号'); End; //-------------执行AT指令继续拨号------------------------// Try DoAtCommand('ATDT'+sPhone+#13+#10); ShowInfo('拨号中。。。。。。'); // Sleep(Timer_Run.Interval-strtointdef(edt_SoundTime.Text,800)-300); Result:=True; Except ShowInfo('拨号失败!'); Exit; End; End; //------------------------拨号主程序----------------------------------------// procedure TFrm_Call.Timer_RunTimer(Sender: TObject); var sPhone,sName:String; nValue:Cardinal; begin //---------循环读取数据库信息 if not ReadInfoFromDataLoop(sPhone,sName) then exit; //读取数据 Edt_Phone.Text:=sPhone; if sPhone='' then Begin ShowInfo('当前数据库电话信息是空的,忽略,继续下一个'); Exit; End; //----------拨号调度主程序--------------// if self.RadioButton_AT.Checked then Begin //-------AT拨号 if hCommFile=Invalid_Handle_Value then exit; ATCall(sPhone); End Else Begin //--------TAPI拨号 Try //APIGetCallStatus(nValue); if PlaySignal then ClosePlay; //停止声音播放 APIStopCall; //停止拨号,LineShutDown级 Call:=0; if not APIDialTest then exit; If not APIDialPrepare then exit; //准备......打开线路 If not APIDial(sPhone) then exit; //重新拨号 if not Timer_Play.enabled then Timer_Play.Enabled:=True; //打开声音播放 ShowInfo('TAPI拨号中......'); Finally End; End; End; //-------------声音播放重复调度程序--------------------// procedure TFrm_Call.Timer_PlayTimer(Sender: TObject); var nValue:dWord; begin if PlaySignal then exit; //如果正在播放,则退出 Try if not APIGetCallStatus(nValue) then exit; //获取状态 //if (nValue<>LineCallState_CONNECTED) or (nValue=LineCallState_DisConnected) then exit; xWaveDevice:=GetWaveDeviceID(); if xWaveDevice=0 then exit; //播放声音 if OpenWaveFile(fWaveFile)=0 then exit; PlayWaveFile(Handle); Except End; End; procedure TFrm_Call.N1Click(Sender: TObject); begin ListBox1.Items.Clear; end; procedure TFrm_Call.N2Click(Sender: TObject); begin if SaveDialog1.Execute then ListBox1.Items.SaveToFile(SaveDialog1.FileName); end; procedure TFrm_Call.cmd_GetWaveFileClick(Sender: TObject); begin if OpenDialog1.Execute then edt_WaveFile.Text:=OpenDialog1.FileName; end; procedure TFrm_Call.cmd_FirmClick(Sender: TObject); begin if trim(edt_Phone.Text)='' then Begin Application.MessageBox('没有电话号码!','电话号',32); exit; End; DialRunType:=2; fWaveFile:=Trim(edt_WaveFile.Text); SndWaveFile:=fWaveFile; //Apistartcall(edt_Phone.Text); Timer_Run.Interval:=StrToIntDef(self.edt_Time.Text,20000); Timer_Play.Interval:=StrToIntDef(self.edt_SoundTime.Text,800); Timer_Run.Enabled:=True; Timer_Play.Enabled:=True; Timer_ShutDown.Enabled:=True; APIStartCall(edt_Phone.Text); end; procedure TFrm_Call.Timer_ShutDownTimer(Sender: TObject); var sValue:string; Begin sValue:=LeftStr(timetostr(time),5); if Trim(edt_ShutDownTime.Text)>sValue then exit; self.cmd_Stop.Click; ExitWindowsEx(EWX_PowerOff,0); End; end.

继续阅读《用普通Modem制作拨号应答中心》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(332) | 评论 (0)编辑 收藏

我的宗旨当然的是建设大富翁为一个精神家园。但是如果一切都“以我为领导和理念”那么会走向个人网站吗?也就是说会不会使得大富翁也象个人网站一样体现出个人魅力,而不是大家的乐园? 所以我必须做的事情就是: 公开:公布可能发生的一切,使得大家都明白,也使得自己明白不是自己一个人在做梦。 无我:不自私,不假公济私,公正无私,这些也是不使得大富翁成为个人网站的关键。 感应:倾听大家的呼声,努力体会并明白大家真实的需求和心态。满足大家。 隐匿:逐渐我将隐匿自己,大家知道我存在就可以,既然舞台是提供给大家的, 我在台前张牙舞爪干嘛呢? 进化:进化也许背后具有某种精神因素存在,否则不可能那么快产生人类,但是进化 的主角还是动物们,不是精神,精神只是指引了方向,提供了环境,那么大富翁 的进化需要更多人的参与。而不是我一个人。 虔诚:既然无我,仍然有愿望,这就是我的工作。

继续阅读《个人网站 vs 精神家园》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(137) | 评论 (0)编辑 收藏

Windows任务栏上显示网页的超酷玩法!!!!!!!!!!! 作者:lee1892 -----------整理者:lnboy 众所周知,windows的任务栏可以显示一个被称为QuickLaunch的快捷工具按钮栏,也可以添加一个指定的目录,并显示该目录下所有文件的按钮。 可您是否知道它还能显示一个html文件的内容吗?它确实可以! 您能想象这有什么作用吗?很有意思的,一起来看看吧。 在任务栏上右键 -> 工具栏 ->新建工具栏.. javascript:window.location.replace("file:///D:/ToolBar/Time/index.html") -------------------------------------------------------------------------------- (此处以位于D:\ToolBar\Time目录下名为index.html的文件为例,此文件稍后给出),这时在Taskbar上会出现java script:window.location等等字样,右键于该字样并刷新之,又可能出现server not found之类的字样,继续右键并刷新之,应该出现该html文件的标题了,调整一下此栏的宽度就可以看到它的内容了。刷新期间,可能会有诸如权限限制之类的对话框跳出,一律yes之。强调一下,是刷新两次。(刷新的时候可能会提示脚本有错,不用理它,多刷新几次就好了) 以下是前述的Time的HTML的源文件 代码:--------------------------------------------------------------------------------<!-- Time--> <html> <head> <title>Time</title> <style> body { border: 0; background-color: buttonface; color: black; margin: 3px,0,0,0 } .clocktxt { font-family: Arial; font-weight: normal; font-size: 8pt } #btnsd { border: 2px groove white; background-color: buttonface; font-family: verdana; font-size: 9px } </style> <script language="JavaScript"> //Clock Script var showclock; function init(){ showdate() showclock=true; } function showdate(){ //edit refresh rate here var refreshrate=1000; var Clock=new Date() var hours=Clock.getHours() var minutes=Clock.getMinutes() var seconds=Clock.getSeconds() var dn="AM" if (hours>12){ dn="PM" hours=hours-12 } if (hours==0) hours=12 if (minutes<=9) minutes= "0" + minutes if (seconds<=9) seconds= "0" + seconds //edit format here format = hours+":"+minutes+":"+seconds+" "+dn; Time.innerHTML=format; if (showclock==false) Time.innerHTML="<input type='button' value='Sh.time' id='btnsd' title='Show time'>" else setTimeout("showdate()",refreshrate) } </script> </head> <body scroll="no" onLoad="init()"> <center> <font class="clocktxt"> <span id="Time" style="position:center;"></span></font> </body> </html> 这样,你就可以在任务栏看到一个时间的显示了。 OK,我们已经知道如何在任务栏上显示HTML文件了。接下来我想您一定知道如何把它拖到边上吧,就是用鼠标点住标题先拖到桌面上,变成一个窗口,再往屏幕边上拖,这样就变成一个Sidebar乐。您可以设置是否自动隐藏、是否永远在最上端等。 在给出几个例子前,先说说写这种HTML的一些小诀窍。 1. 显示与任务栏颜色相同的背景色 在<head>段里加入 代码:--------------------------------------------------------------------------------<Style> body { border-width : 0 ; background-color: buttonface; ... }</Style>-------------------------------------------------------------------------------- 这样当更换Theme时,回一同更换 2. 自动刷新页面 有些情况下会希望网页自动刷新,可以在<head>段里加入 代码:--------------------------------------------------------------------------------<meta http-equiv="Refresh" content="60">-------------------------------------------------------------------------------- content的数字应该是秒吧(记不清了,呵呵) 3. 禁止滚动条 代码:--------------------------------------------------------------------------------<body scroll="no">-------------------------------------------------------------------------------- 4. 设置页面的边距 在body的style设定里加入 代码:-------------------------------------------------------------------------------- margin: 2,2,2,2 -------------------------------------------------------------------------------- 差点忘了说,我的机子上,必须在任务栏上加新的,也就是说每加一个新的必须从头做起(在任务栏上右键...拖到桌面再拖到边上),不知道您得是否也这样 下面是几个示例的部分代码: 示例一: 万年历 代码:--------------------------------------------------------------------------------HTML QuickLaunch /// Calendar by Lee1892 Original file from http://hohula.myetang.com/html/calendar.html java script:window.location.replace("file:///x:/.../Calendar/index.html") You can change the rows 1246-1262 to hide or show some parts. for example to hide part WorldTime, change line 1246 and 1247 original: WorldTime.style.visibility='visible' //'hidden' WorldTime.style.position='relative' //'absolute' change to: WorldTime.style.visibility='hidden' //'visible' WorldTime.style.position='absolute' //'relative' You must know the word after // is only comments in JS:) 示例二: 中华网实时滚动新闻 代码:--------------------------------------------------------------------------------HTML QuickLaunch /// China News by Lee1892 java script:window.location.replace("file:///x:/.../ChinaNews/index.html") You can change the news you want to show at line 41 original: <script language="JavaScript" src="http://app0.china.com/freecode/out.php?typeid =945&num=20&t=否"></script> The number after 'typeid' indicate the news' catalog (see table below) 264 文化传真页面 1055 教育新闻页面 420 股市动态页面 567 财经要闻 205 影视焦点页面 764 医药快讯页面 777 两性话题页面 25 军事评论页面 64 军事要闻页面 167535 撞机页面 945 中国新闻页面 1007 社会新闻页面 1000 国际新闻页面 1024 要闻提示页面 1040 国内足球新闻页面 1221 NBA新闻页面 1066 世界网球新闻页面 1047 国际足球新闻页面 154 科技新闻页面 156 互联网络新闻页面 896 通信聚焦新闻页面 You should also check page http://app0.china.com/freecode/freenews.php to see the latest infomation. You also change the number of news you want to show, locates at line 41 and 57 At line 41, the number after 'num', and at line 57 is the value of variable NewsItem. Change them to a same number which should be 10, 20, 30 ... 100. 示例三: 天气在线 代码:--------------------------------------------------------------------------------HTML QuickLaunch /// Weather by Lee1892 Infomations are from http://www.t7online.com/ java script:window.location.replace("file:///x:/.../Weather/index.html") You should check you local city ID from http://www.t7online.com/ first, and then change line 98 original: var MyCityURL="http://www.t7online.com/cgi-bin/citybild?PROVIDER=anwendung&WMO=58362&LANG=cn" Change number after 'WMO=' to your local city ID. 示例四: Winamp控制 代码:--------------------------------------------------------------------------------HTML QuickLaunch /// RunBox by [kmr] java script:window.location.replace("file:///x:/...//HTMLql/AmpBar/index.html") A winamp control. You need the WinampCOM plugin (http://www.adcock8.freeserve.co.uk) for the page to work properly. Double-click the window to activate/desactivate the auto song info update.-------------------------------------------------------------------------------- 这个呢就不是我自己做的乐,他给出的WinampCOM主页也换到http://mysite.freeserve.com/johnadcock了,不过应该是不支持3.0的,呵呵 示例五: RunBox,即在栏内键入命令即可运行,等同于Run对话框的功能 代码:--------------------------------------------------------------------------------<html> <head> <title>Run Box</title> <style> body { border-width: 0; background-color: buttonface; color: black; font-family: verdana; font-size: 9px; margin: 3,0,0,0 } </style> <script language="JavaScript"> function Open(appName) { //var appName="explorer /root,,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"; var WshShell = new ActiveXObject("WScript.Shell"); WshShell.Run(appName,1); window.blur(); } </script> </head> <body scroll="no"> <form onsubmit="Open(document.all.T1.value)"> <p><input type="text" name="T1" size="10" height="5"></p> </form> </body> </html>-------------------------------------------------------------------------------- 其实,windows自带的Address那个Toolbar就可以,之所以给出此例是想说明如何用HTML启动程序,呵呵 最后的几句话: 我想说的是我做的几个示例都还是很不成熟的,只是给大家一些想法。 我们知道HTML加上VBS和JS是十分强大的(比如对于Windows Messenger,有MAPI,不知道VBS能调用不?),还有花哨的Flash,您甚至可以把flash放到自己做的Sidebar里(比如一个好玩的小游戏,这样就成了一个真正的桌面游戏了)。 还有很多很多可以做的东西,您一定有更多的想法或更好的实现方法。请来参加讨论吧,哪怕只是一些设想(或许有高手知道如何实现呢)。 我只是一个抛砖的人 -------------------------------------------------------------------------------- 以上内容由lnboy整理收藏,原帖在http://bbs.et8.net/bbs/

继续阅读《Windows任务栏上显示网页的超酷玩法!!!!!!!!!!!》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(314) | 评论 (0)编辑 收藏

新买回来的耳机,听感不错。可是与朋友的用了有一段时间的同型号耳塞对比起来,总是差强人意。低音紧而生硬,中音不够柔和丰满,高音部分毛刺尽显。为什么会这样呢?因为这只新买的耳机还没有褒过!   那么,何谓褒耳机?大家都知道,新的汽车,机器等,在正常使用前都是要经过一个叫做“磨合”的阶段,使内部的机械装置充分协调配合,提前进入到最佳状态。同样,耳机的推动单元(耳机里边的扬声器)也是一个机械装置,准确来说应该是半机械、半电子的结合物,主要由音圈、震膜、定位环(固定震膜的金属环)等组成。机械部分属于顺性系统,包括震膜和固定在震膜上的音圈。顺性元件可以等效于电子元件中的电容,电容储存的是电能,震膜和音圈储存的是动能。耳机单元顺性的大小就等同于震膜和音圈这两个电容的并联值,也就是是决定音质好坏的关键。震膜和音圈所使用的材料是高顺性材料,其内部分子结构在定型初期不稳定,所以顺性大小也不稳定,刚转用在扬声器单元上时其顺性通常比较小(通常直观的理解就是还比较生硬),因为分子结构相对处于稳定期。长时间地运动之后,分子之间距离拉远,分布均匀顺性加大许多,扬声器整体的顺性也加大许多,扬声器一个最重要的数值就是最低谐振频率,专业上叫F0,这个值基本决定了扬声器所能达到的最低频率,它取决于扬声器的等效质量和等效顺性,因为扬声器是一个机械共振系统等效于一个电路上的共振电路,共振电路的频率取决于电感(扬声器等效质量)和电容的大小,FO的大小和电感与电容的大小成反比,所以扬声器顺性越大,扬声器的F0就越低,低频下潜就越好。顺性的变化牵一发动全局,扬声器整体的所有机械数据动会变化,如扬声器的机械品质因数,顺性大了就等于机械损耗增加,因此机械品质因数会变低,就等同于声音听起来比较松软。所以新的耳机相对听起来都有低频下潜不深、量感也较小、生硬,中频表现不够柔和,高频还有毛刺、太过尖锐等症状(当然,这也是由耳机本身的素质决定的)。褒一段时间后,扬声器单元的顺性(或说弹性)增加,前后移动会轻松自如,这样声音就会丰满轻松,音质也就好一些了。 那么,要如何褒耳机呢?以前流行一种很简单的方法,就是直接接上收音机,调到一个无电台的频率上,利用收音机发出的“嘶嘶”声(粉红色噪音)长时间让耳机工作,以达到褒机的效果。但用这个方法不太明显,还不如直接戴上耳机听音乐这样来得更快。也有用专门的频率发生器来生成某一段固定或扫描的频率然后输入到耳机这样来褒的,这种方法效果比较明显,所使用的时间也能缩短很多。但是大部分的玩家都没有这一类的仪器,那怎么办呢?用什么方法褒耳机最有效率呢?在计算机发展日新月异的今天,很多的爱好者编出了一些程序,利用计算机处理出一些波形、频率,通过声卡输出,达到一些真实频率发生仪器的效果,这就是所谓的“虚拟仪器”。类似这样的频率测试软件有很多,笔者现在用的是一个叫Test Tone Generator的软件,简单易用,功能专一,体积也小。 附几个url: http://www.imp3.net/lb5000/cgi-bin/topic.cgi?forum=8&topic=3243 http://www.pconline.com.cn/digital/textlib/audio/md/04/10302/135131.html http://www.imp3.net/lb5000/cgi-bin/topic.cgi?forum=8&topic=4972 http://www.imp3.net/lb5000/cgi-bin/topic.cgi?forum=8&topic=8524&show=180

继续阅读《何谓“褒耳机”》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(151) | 评论 (0)编辑 收藏

突然,发现自己对算法已经很生疏了,象最短路径,邻接矩阵等名词似乎很熟,但细想一下,该怎么实现呢?才发现,自己已经忘掉了他们.于是,想闲来温习一下,最后选了这本书,很不错,还可以温习一下C++的好多东西,我手上的版本是机械工业出版社 2000年1月第1版.今天就算起个头吧,接下来的日子中我会将学习中的心得和问题一点一滴记录下来,以加深学习的效果

继续阅读《<数据结构算法与应用(C++语言描述)>学习笔记》的全文内容...



--------------------------
新闻:鲍尔默:不解Google为何推出两款操作系统
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-07-15 10:28 delphi2007 阅读(154) | 评论 (0)编辑 收藏

2009年6月10日 #

 
  我用ado+sqlserver作开发,  
  在数据操作一半的时侯网络掉线了,要怎么才可以在重新上线的时侯依然可以把现在的数据表中的内容更新到数据库中呢?

继续阅读《网络掉线后更新问题》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(179) | 评论 (0)编辑 收藏

我的程序是这样的  
  TreturnDbname=function():String;stdcall;  
   
  procedure   TForm1.Button1Click(Sender:   TObject);  
  var  
        returnDbname   :   TReturnDbname;  
        AHandle:   THandle;  
  begin  
   
          CoInitialize(nil);  
          AHandle:=LoadLibrary('CreatePro.dll');  
          try  
                if   AHandle<>0   then  
                      @returnDbname:=GetProcAddress(AHandle,'returnDbName');  
                      if   not(@returnDbname=nil)   then  
                      begin  
   
                              dbname:=returnDbname();  
                              showmessage('dbname='+dbname);  
                      end;  
          finally  
                  freeLibrary(AHandle);  
          end;  
  end;  
  我把freeLibrary(AHandle);注释掉程序执行完了关闭窗口时,但是整个project1却没有关闭依然在内存里运行着;而加上freeLibrary(AHandle);在程序运行完毕连showmessage('dbname='+dbname);也执行对了点击showmessage出现的窗口后就出现这样的错误:Access   violation   at   address   00403F7E   in   module   'project1.exe'.Read   of   address   0168B792C.请问这是什么原因啊,该怎么解决,谢谢!

继续阅读《加载dll时出现的问题》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(200) | 评论 (0)编辑 收藏

rt

继续阅读《DBGridEh控件是免费的吗?能自由使用吗?》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(359) | 评论 (0)编辑 收藏

DB数据库密码怎么破啊~~~求高手帮忙解决下~  
  就是传奇服务端里面的  
  Hum.DB  
  Mir.DB  
  Id.DB  
  这3个DB数据库文件  
  请问他密码怎么破解啊~~~

继续阅读《DB数据库密码怎么破啊~~~求高手帮忙解决下~》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(250) | 评论 (0)编辑 收藏

一个表中有若干记录,其中有个字段是数字类型,但不是必填的,  
  如何从这个表中删除那些值位空的记录?sql语句怎么写?

继续阅读《如何从这个表中删除那些值位空的记录?sql语句怎么写?》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(199) | 评论 (0)编辑 收藏

一个表如下:  
  日初始数(S)       日入数(R)     日出数(C)     日存量(ZL)  
          0                           3                     2  
                                      5                     1  
                                      3                     2  
                                      ..........  
  能不能用精简的SQL语句将表的     S   列     与   ZL列填上值   结果为      
   
  日初始数(S)       日入数(R)     日出数(C)     日存量(ZL)  
  0                                   3                     2                   1  
  1                                   5                     1                   5  
  5                                   3                     2                   6  
                                      ..........  
   
  即   zl   =s+   r-c    
  S   为上一天的存量  
   
   
           
 

继续阅读《SQL语句更新一个表的上下行的问题(急)》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(194) | 评论 (0)编辑 收藏

嗨,大家好!  
  procedure   TForm1.Button3Click(Sender:   TObject);  
  begin  
      With   ADOQuery1   do  
      begin  
          Close;  
          SQL.Clear;  
          SQL.Add('Select   *   from   a   ');  
          Open;  
          DBEdit1.DataSource   :=   DataSource2;  
          DBEdit1.DataField   :=   '题号';  
          DBEdit2.DataSource   :=   DataSource2;  
          DBEdit2.DataField   :=   '题目';  
        end;  
  end;  
   
  procedure   TForm1.Button4Click(Sender:   TObject);  
  begin  
   
      With   ADOQuery1   do  
      begin  
          Close;  
          SQL.Clear;  
          SQL.Add('Select   *   from   S1   ');  
          Open;  
          DBEdit1.DataSource   :=   DataSource1;  
          DBEdit1.DataField   :=   '题号';  
          DBEdit2.DataSource   :=   DataSource1;  
          DBEdit2.DataField   :=   '正确答案';  
        end;  
  end;  
   
  怎么我在按了Button3后在按Button4就出错呢?    
 

继续阅读《数据显示问题!》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(123) | 评论 (0)编辑 收藏

小弟在自己电脑上装SQL   SERVER   2000失败后,装了MSDE(是成功安装了的),可是在用SQLDMO枚举的时候,找不到服务器,得到的列表是空的。可是用ADOTABLE和ADOCONNECTION能成功连接服务器,而且在VFP9。0R的DATAEXPLORE下也能成功连接,  
   
  不知为什么?因为自己现在在网吧,无法贴出相关代码。请高手指教一二?是MSDE本身的问题,还是非曲直MSDE本来无法被SQLDMO.APPLICATION枚举到?  
   
  多谢了  
   
  另外,哪位大侠有用SQLDMO来创建数据库的DELPHI代码?多谢了?  
 

继续阅读《关于SQLDMO中枚举SQL服务器》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(206) | 评论 (0)编辑 收藏

向dbf(dbase5)数据库中插入中文数据是乱码,该怎么解决???

继续阅读《dbf数据库问题???急啊》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(201) | 评论 (0)编辑 收藏

存在数据库里的某个字段类型是VCHAR,其内容是越南文.在数据库里是正常的.为什么用DELPHI   读出来后会乱码?  
  我是这样读取的adoquery1.FieldByName('Address').AsString.是不是AsString的时候转换了编码???急啊!!!!

继续阅读《数据库读取问题》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(142) | 评论 (0)编辑 收藏

以前開發的數據庫,現在我在一個表中新增加了一個字段,但現在在使用datacontrol上的控件關鏈這個表的時候,為何在datafield中選擇字段的時候,為何不顯示新增加的字段,而只有以前的字段....

继续阅读《超急簡單問題!》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(139) | 评论 (0)编辑 收藏

var  
      is_Diff,StartSNoRight:String;  
      StartSNoRightValue:integer;  
  begin  
        StartSNoRightValue:=StrToint(StartSNoRight)+StrToint(is_Diff);  
       
  StartSNoRight   是10位的数字   ,StrToint转换就超出了     该用什么函数阿   ?  
  在线等

继续阅读《数据类型转换 在线等》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(107) | 评论 (0)编辑 收藏

我用Delphi自带的制作帮助文档工具制作帮助文档!  
  用Word编辑rtf文件。然后运行的时候,我单击帮助文档上的链接的时候它说找不到相应的主题!!!  
  这是怎么回事?  
   
  用Word编辑rtf文件时要怎样处理主题?使单击的时候显示相应主题的内容!!!  
  哪位大虾说下具体的做法?  
  非常感谢!!!急!急!!!!

继续阅读《帮助文档?》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(232) | 评论 (0)编辑 收藏

大家好,有两个表  
  表a     数量   名称         型号         表b     数量       名称         生产日期  
            100       避雷器     XX                       1001         避雷器     yy-mm-dd  
            ..         ..           ..                         ..           ..           ......  
  想将表b中与表a中名称相同的产品的数量加到表a中   然后再在表a中查询显示出来  
   
  用如下   语句  
  select   a.名称,a.数量=a.数量+b.数量    
  from   a,b  
  where   a.名称=b.名称  
  来执行显示  
  结果在DbGrid中   数量这个字段的值为O   并且所显示的“数量”也变成了"Expr1001",  
   
  不知为什么请各位高手指点。。

继续阅读《sql 相加后查询》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(359) | 评论 (1)编辑 收藏

我用Installshield5.0来制作安装程序,制作好后,我运行安装程序,可以安装,但是运行桌面上的程序快捷图的时候,它说找不到数据源(比如我用的数据源GXCQ),但是在控制面板中的BDE       Administrator中为其手工配置一个数据库别名(GXCQ),这样就可以运行程序了,以后不须再配置BDE了!  
   
  哪能让用户安装程序的时候自己加数据源,没有一个软件是像这样的!  
  请问怎样让在制作安装程序的时候让它自动安装的时候加上数据源呀!!!  
  急呀!!!  
  哪位大虾帮下忙?谢谢!!!  
   
 

继续阅读《安装程序的问题?》的全文内容...



--------------------------
新闻:一款软件何以管理一个复杂的社会
网站导航: 博客园首页  新闻  .NET频道  社区  博问  闪存  找找看
posted @ 2009-06-10 13:54 delphi2007 阅读(125) | 评论 (0)编辑 收藏

仅列出标题  下一页