在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
///环境:Winxp + D7
///进入D7,在默认的新建工程中增加一过程Test(m: Array of const); procedure TForm1.test(m: array of const); var i, zero: Integer; s, t: String; c: Char; const sBoolean: Array [Boolean] of string = ('False', 'True'); begin s := ''; for i := 0 to High(m) do with m[i] do case VType of //写到这,按住Ctrl点击VType,打开System单元,将VType的枚举值贴到Case语句 vtInteger: (VInteger: Integer; VType: Byte); vtBoolean: (VBoolean: Boolean); vtChar: (VChar: Char); vtExtended: (VExtended: PExtended); vtString: (VString: PShortString); vtPointer: (VPointer: Pointer); vtPChar: (VPChar: PChar); vtObject: (VObject: TObject); vtClass: (VClass: TClass); vtWideChar: (VWideChar: WideChar); vtPWideChar: (VPWideChar: PWideChar); vtAnsiString: (VAnsiString: Pointer); vtCurrency: (VCurrency: PCurrency); vtVariant: (VVariant: PVariant); vtInterface: (VInterface: Pointer); vtWideString: (VWideString: Pointer); vtInt64: (VInt64: PInt64); end; Delete(s, 1, 1); Self.Caption := s; end; ///继续写,对各枚举值进行处理!这里作一下解释,Array of const正是由TVarRec类型组成的! ///请看Case of语句中的代码: vtInteger: s := s + ';' + IntToStr(VInteger); vtBoolean: s := s + ';' + sBoolean[VBoolean]; vtChar: s := s + ';' + VChar; vtExtended: s := s + ';' + FloatToStr(VExtended^); vtString: if Assigned(VString) then begin t := VString^; s := s + ';' + t; end; vtPointer: if Assigned(VPointer) then s := Format('%S; Pointer: $%X ',[s, Integer(VPointer)]); vtPChar: if Assigned(VPChar) then begin t := VPChar^; s := s + ';' + t; end; vtObject: if Assigned(VObject) then s := Format('%S; $%X ClassName: %S ',[s, Integer(@VObject), VObject.ClassName]); vtClass: if Assigned(VClass) then s := Format('%S; Class Reference $%X - ClassName: %S ',[s, Integer(VClass), VClass.ClassName]); vtWideChar: begin t := VWideChar; s := s + ';' + t; end; vtPWideChar: if Assigned(VPWideChar) then begin t := VPWideChar^; s := s + ';' + t; end; vtAnsiString: if Assigned(VAnsiString) then begin t := PChar(VAnsiString); s := s + ';' + t; end; vtCurrency: if Assigned(VCurrency) then s := s + ';' + FloatToStr(VCurrency^); vtVariant: if Assigned(VVariant) then s := s + '; This is variant '; vtInterface: if Assigned(VInterface) then s := Format('%S; Interface: $%X',[s, Integer(VInterface)]); vtWideString: if Assigned(VWideString) then begin t := PWideString(VWideString)^; s := s + ';' + t; end; vtInt64: if Assigned(VInt64) then s := s + ';' + IntToStr(VInt64^); 加上一按钮测试该函数
procedure TForm1.Button1Click(Sender: TObject);
var ws: WideString; begin ws := 'dda这是一个测试dfa'; test([self, 'sdf', 2.3324, ws, TForm]); end; 可以看到测试结果,变量ws的值没有显示出来,怎么办呢? 我们可以看到WideString类型的值是指针,我们就从这里着手,在事件中添加一句: Button1.Caption := Format('$%X',[Integer(@ws)]); 此句的作用是显示出ws的地址 再在Test函数中也加上类似的语句,并注释掉无用的语句: //t := PWideString(VWideString)^; //s := s + ';' + t; s := s + ';' + Format('$%X',[Integer(VWideString)]); 运行可看到二个地址不一样,说明Delphi对传入的参数数据作了复制 因此将其强制转换成PWidechar应该可以,增加一变量声明 w: WideString; w := PWideString(VWideString)^; s := s + ';' + w; 但运行结果却只显示一个字符,别沮丧,已经摸到门道了! 我们知道Format可以处理Widestring类型,这里只得到一个字符,说明字符被截断了。Delphi中的字符串是以#0结束,Widestring以二个#0结束,可以肯定w := PWideString(VWideString)^这句Delphi作转换时肯定将其默认作为AnsiString处理了。分析到这里已经可动手写下去了..... p: PByte; if Assigned(VWideString) then begin t := ''; zero := 0; p := VWideString; repeat c := char(p^); inc(p); if c = #0 then inc(zero) else begin zero := 0; t := t + c; end; until zero = 2; s := s + ';' + t; end; 但是显示汉字却变成乱码了,而且处理也显得臃肿。到这里我们已经明白了,VWideString所指示的字符串是二字节宽字符串,而且Intel的字节顺序也是低位在前,高位在后。因此可用PWord进行处理! 删除c,zero,w变量,p改成: p: PWord; if Assigned(VWideString) then begin t := ''; p := VWideString; repeat t := t + widechar(p^); inc(p); until p^ = 0; s := s + ';' + t; end; 可以看到核心代码已经很精练了,运行已经显示正常,汉字也无乱码了!至此我们似乎是大功告成了,但静下来想想,Delphi支持WideString到String的转换,它也应该有这样的处理代码。 而且在循环中t := t + widechar(p^);语句处下一断点,运行到断点处,再打开CPU窗口,看到看似简洁的代码,单此一句,编译器都要给它加上一大堆处理代码。找到系统的字符串处理函数很有必要,经过在System.pas单元中搜索WideString,找到函数:procedure WideCharToStrVar(Source: PWideChar; var Dest: string); 呵呵,这正是我们要的!!! 现在循环语句及P变量都可删除了,代码我就省略了。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论