TMessage = packed record
    Msg: Cardinal;
    case Integer of
      0: (
        WParam: Longint;
        LParam: Longint;
        Result: Longint);
      1: (
        WParamLo: Word;
        WParamHi: Word;
        LParamLo: Word;
        LParamHi: Word;
        ResultLo: Word;
        ResultHi: Word);
  end;
再定义这个结构中,我不明白case地用法在这里是什么意思,帮忙解释一下,谢谢

解决方案 »

  1.   

    很简单啊,你可以使用Msg.Wparam来调用,也可以使用Msg.WparamLo+Msg.WparamHi调用
      

  2.   

    哦,case在这里就是提供两种定义是么?
    没有别的特殊的含义?
      

  3.   

    首先这个结构中以长度为3*32bit
    其中WParam为32bit 他由WParamLo 和WParamHi 组成(各16bit)
    在引用时可以分别以32bit和16bit两种方法使用
      

  4.   

    TMSHMouseWheel = packed record
        Msg: Cardinal;
        WheelDelta: Integer;
        case Integer of
          0: (
            XPos: Smallint;
            YPos: Smallint);
          1: (
            Pos: TSmallPoint;
            Result: Longint);
      end;  TSmallPoint = packed record
        x: SmallInt;
        y: SmallInt;
      end;
    那这种结构呢,我就想知道case的这种用法给用户提供的借口是两个,但是编译器是怎么处理的呢?
      

  5.   

    看《delphi高手突破》的时候遇到过,当时也感到很奇怪,关注....
      

  6.   

    你这种记录类型,叫变体记录类型,也就是你发消息的时候可以以两种不同形式发出,至于怎么知道你发的是哪种类型,VCL帮你搞定啦!你可以看看variant类型的定义。
      

  7.   

    var
      Form1: TForm1;
      msg:TMessage;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
        msg.WParam:=100;
        edit1.Text:=IntToStr(msg.WParamLo);
        edit2.Text:=IntToStr(msg.WParamHi);
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
        msg.WParamLo:=StrToInt(edit1.Text);
        msg.WParamHi:=StrToInt(edit2.Text);
        edit3.Text:=IntToStr(msg.WParam);
    end;end.
    --------------------
    作了一个测试,意思好像就是相同分配的内存有两种访问方式把
    感觉也没有太特别的...
      

  8.   

    内存共享,比如procedure TForm1.FormCreate(Sender: TObject);
    type test=record
      case boolean of
        false:(ByteVar:byte);
        true :(CharVar:char);
      end;
    var aTest:Test;
    begin
      aTest.ByteVar:=65;
      memo1.Lines.Add('CharVar:'+aTest.CharVar);
      aTest.CharVar:='a';
      memo1.Lines.Add('ByteVar:'+inttostr(aTest.ByteVar));  memo1.Lines.Add('CharVar地址:'+inttostr(integer(@aTest.ByteVar)));
      memo1.Lines.Add('ByteVar地址:'+inttostr(integer(@aTest.ByteVar)));
    end;
      

  9.   

    首先case integer of 0还是1还是2没有什么关系,你定义成case 3 也行,只是做为两种不同结构的分隔符而已,其次,结构体是按位分配内存的,连续的内存,所以,当你要访问case中间的数据时,如果你访问XPos,就返回WheelDelta后的4个字节的smallint,如果你访问TSmallPoint 就返回WheelDelta后的8个字节,不知道我理解的对不对,:),我的基础也不好
      

  10.   

    dinglinger(叮当)叫变体记录类型,也就是你发消息的时候可以以两种不同形式发出,至于怎么知道你发的是哪种类型
    /////我觉得它的发送形式都是一样的,主要是使用的时候可以用不同的解析方式吧???
    WParam: Longint;

    WParamLo: Word;
    WParamHi: Word;
    应该没有本质的区别的...
      

  11.   

    TMSHMouseWheel = packed record
        Msg: Cardinal;
        WheelDelta: Integer;
        case Integer of
          0: (
            XPos: Smallint;
            YPos: Smallint);
          1: (
            Pos: TSmallPoint;
            Result: Longint);
      end;  TSmallPoint = packed record
        x: SmallInt;
        y: SmallInt;
      end;
    那这种结构呢,我就想知道case的这种用法给用户提供的借口是两个,但是编译器是怎么处理的呢?
    //////////////////////这种情况下,好像0/1的内存长度就不想等了,这个怎么办的那???
      

  12.   

    我当它是c里面的联合(union)结构理解,因为我以前也问过,下面是delphi help的内容:
    keyword: Variant parts in recordsA record type can have a variant part, which looks like a case statement. The variant part must follow the other fields in the record declaration.
    To declare a record type with a variant part, use the following syntax.type recordTypeName = record  fieldList1: type1;
      ...
      fieldListn: typen;
    case tag: ordinalType of
      constantList1: (variant1);
      ...
      constantListn: (variantn);
    end;The first part of the declaration梪p to the reserved word case梚s the same as that of a standard record type. The remainder of the declaration梖rom case to the optional final semicolon梚s called the variant part. In the variant part,tag is optional and can be any valid identifier. If you omit tag, omit the colon (:) after it as well.
    ordinalType denotes an ordinal type.
    Each constantList is a constant denoting a value of type ordinalType, or a comma-delimited list of such constants. No value can be represented more than once in the combined constantLists.
    Each variant is a comma-delimited list of declarations resembling the fieldList: type constructions in the main part of the record type. That is, a variant has the formfieldList1: type1; ...
    fieldListn: typen;where each fieldList is a valid identifier or comma-delimited list of identifiers, each type denotes a type, and the final semicolon is optional. The types must not be long strings, dynamic arrays, variants (that is, Variant types), or interfaces, nor can they be structured types that contain long strings, dynamic arrays, variants, or interfaces; but they can be pointers to these types.Records with variant parts are complicated syntactically but deceptively simple semantically. The variant part of a record contains several 
    variants which share the same space in memory. You can read or write to any field of any variant at any time; but if you write to a field in one variant and then to a field in another variant, you may be overwriting your own data. The tag, if there is one, functions as an extra field (of type ordinalType) in the non-variant part of the record.Variant parts have two purposes. First, suppose you want to create a record type that has fields for different kinds of data, but you know that you will never need to use all of the fields in a single record instance. For example,type  TEmployee = record
      FirstName, LastName: string[40];
      BirthDate: TDate;
      case Salaried: Boolean of
        True: (AnnualSalary: Currency);
        False: (HourlyWage: Currency);
    end;The idea here is that every employee has either a salary or an hourly wage, but not both. So when you create an instance of TEmployee, there is no reason to allocate enough memory for both fields. In this case, the only difference between the variants is in the field names, but the fields could just as easily have been of different types. Consider some more complicated examples:type  TPerson = record
      FirstName, LastName: string[40];
      BirthDate: TDate;
      case Citizen: Boolean of
        True: (Birthplace: string[40]);
        False: (Country: string[20];
                EntryPort: string[20];
                EntryDate, ExitDate: TDate);
      end;type  TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
      TFigure = record
        case TShapeList of
          Rectangle: (Height, Width: Real);
          Triangle: (Side1, Side2, Angle: Real);
          Circle: (Radius: Real);
          Ellipse, Other: ();
      end;For each record instance, the compiler allocates enough memory to hold all the fields in the largest variant. The optional tag and the constantLists (like Rectangle, Triangle, and so forth in the last example above) play no role in the way the compiler manages the fields; they are there only for the convenience of the programmer.
    The second reason for variant parts is that they let you treat the same data as belonging to different types, even in cases where the compiler would not allow a typecast. For example, if you have a 64-bit Real as the first field in one variant and a 32-bit Integer as the first field in another, you can assign a value to the Real field and then read back the first 32 bits of it as the value of the Integer field (passing it, say, to a function that requires integer parameters).
      

  13.   

    type
    TMSHMouseWheel = packed record
        Msg: Cardinal;           //4
        WheelDelta: Integer;     //4
        case  tag:Integer of     //4 这个tag:可以缺省,不过加上去会多用去4个字节
          0: (
            XPos: Smallint;      //2
            YPos: Smallint);     //2
          1: (
            Pos: TSmallPoint;    //4
            Result: Longint);    //4
      end;  TSmallPoint = packed record
        x: SmallInt;
        y: SmallInt;
      end;
    var MSHMouseWheel:TMSHMouseWheel;
        AnyVar:integer;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      memo1.Lines.Add('MSHMouseWheel:'+inttostr(integer(@MSHMouseWheel)));
      memo1.Lines.Add('Msg地址:'+inttostr(integer(@MSHMouseWheel.Msg)));
      memo1.Lines.Add('WheelDelta地址:'+inttostr(integer(@MSHMouseWheel.WheelDelta)));
      memo1.Lines.Add('tag地址:'+inttostr(integer(@MSHMouseWheel.tag)));
      memo1.Lines.Add('XPos地址:'+inttostr(integer(@MSHMouseWheel.XPos)));
      memo1.Lines.Add('YPos地址:'+inttostr(integer(@MSHMouseWheel.YPos)));
      memo1.Lines.Add('Pos地址:'+inttostr(integer(@MSHMouseWheel.Pos)));
      memo1.Lines.Add('Pos.x地址:'+inttostr(integer(@MSHMouseWheel.Pos.x)));
      memo1.Lines.Add('Pos.y地址:'+inttostr(integer(@MSHMouseWheel.Pos.y)));
      memo1.Lines.Add('Result地址:'+inttostr(integer(@MSHMouseWheel.Result)));
      memo1.Lines.Add('SizeOfMSHMouseWheel:'+inttostr(SizeOf(MSHMouseWheel)));
      memo1.Lines.Add('AnyVar地址:'+inttostr(integer(@AnyVar)));
      //case integer是编译器预编译的,就是说在编译时就确定的变量的类型和地址,不需要在
      //运行期去区分,只需要去调用 MSHMouseWheel.Pos.x 或者  MSHMouseWheel.XPos,他们的
      //地址在运行期是不用去关心的 ,下面这样改变tag的值对这个结构的定义是没有任何影响的
      pinteger(@MSHMouseWheel.tag)^:=1;
      pinteger(@MSHMouseWheel.tag)^:=0;
    end;