Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Form doesn't resize when set width :(

tijoentijoen Member Posts: 141
Hi, read this code:
[code]
var
x: ^Integer;
begin
showmessage(inttostr(self.Width));
x := @Self.width;
x^ := 40;
showmessage(inttostr(self.Width));
end;
[/code]
When you do the code above, the form does not resize

but, when you do this one below, it resizes
[code]
begin
Self.width := 40;
end;
[/code]

I am working with pointers, so when the variable x is set, in fact I don't know if it is the width of the object or not, it can be the Top or whatever
what can I do?

thank you

Using Delphi 7

Comments

  • zibadianzibadian Member Posts: 6,349
    : Hi, read this code:
    : [code]:
    : var
    : x: ^Integer;
    : begin
    : showmessage(inttostr(self.Width));
    : x := @Self.width;
    : x^ := 40;
    : showmessage(inttostr(self.Width));
    : end;
    : [/code]:
    : When you do the code above, the form does not resize
    :
    : but, when you do this one below, it resizes
    : [code]:
    : begin
    : Self.width := 40;
    : end;
    : [/code]:
    :
    : I am working with pointers, so when the variable x is set, in fact I
    : don't know if it is the width of the object or not, it can be the
    : Top or whatever
    : what can I do?
    :
    : thank you
    :
    : Using Delphi 7

    Width is not a variable or a field, but a property. Properties are can be pointers to functions. Since you do not know if TForm.Width isn't an access method, you don't know what x := @Form1.Width is.
  • tijoentijoen Member Posts: 141
    : Width is not a variable or a field, but a property. Properties are
    : can be pointers to functions. Since you do not know if TForm.Width
    : isn't an access method, you don't know what x := @Form1.Width is.

    ok but, what variable or access method should I point to, to when I set it, it changes the width?
    any ideas?
    oh, I forgot, did you run the code i posted?
    the showmessage will tell you that the x^ := 40; did set the form's width
    thats why its strange

    thanks for the answer!

    Joe
  • zibadianzibadian Member Posts: 6,349
    : : Width is not a variable or a field, but a property. Properties are
    : : can be pointers to functions. Since you do not know if TForm.Width
    : : isn't an access method, you don't know what x := @Form1.Width is.
    :
    : ok but, what variable or access method should I point to, to when I
    : set it, it changes the width?
    : any ideas?
    : oh, I forgot, did you run the code i posted?
    : the showmessage will tell you that the x^ := 40; did set the form's
    : width
    : thats why its strange
    :
    : thanks for the answer!
    :
    : Joe

    Normally access methods are private and the fields of the properties are always private. In case of a TForm the Width access method (SetWidth) is private as well, based on D5.
    As for pointing to an access method: access methods for non-indexed properties have this form:
    [code]
    procedure TForm.SetWidth(const value: integer);
    [/code]
    If you want to use pointer to set the width (even if SetWidth() were protected or more visible), the code would look like this:
    [code]
    type
    TSetInt = procedure(const value: integer) of object;

    var
    AccessMethod: TSetInt;
    begin
    TMethod(AccessMethod).Code := Form1.SetWidth;
    TMethod(AccessMethod).Data := Form1;
    AccessMethod(x);
    end;
    [/code]
    The type TSetInt would only work for integer properties, but not for any other type, even if they are compatible with integer.

    It is also not strange that the ShowMessage() shows the updated width, because the TForm (defined in TControl) does have a width field, which is updated. The problem is that windows never is notified of the new width, which is the task of SetWidth(). The property width simply returns the field FWidth.

    The easiest way around this problem is to define your own set procedure, in which you can select which property to update.
  • tijoentijoen Member Posts: 141

    : Normally access methods are private and the fields of the properties
    : are always private. In case of a TForm the Width access method
    : (SetWidth) is private as well, based on D5.
    : As for pointing to an access method: access methods for non-indexed
    : properties have this form:
    : [code]:
    : procedure TForm.SetWidth(const value: integer);
    : [/code]:
    : If you want to use pointer to set the width (even if SetWidth() were
    : protected or more visible), the code would look like this:
    : [code]:
    : type
    : TSetInt = procedure(const value: integer) of object;
    :
    : var
    : AccessMethod: TSetInt;
    : begin
    : TMethod(AccessMethod).Code := Form1.SetWidth;
    : TMethod(AccessMethod).Data := Form1;
    : AccessMethod(x);
    : end;
    : [/code]:
    : The type TSetInt would only work for integer properties, but not for
    : any other type, even if they are compatible with integer.
    :
    : It is also not strange that the ShowMessage() shows the updated
    : width, because the TForm (defined in TControl) does have a width
    : field, which is updated. The problem is that windows never is
    : notified of the new width, which is the task of SetWidth(). The
    : property width simply returns the field FWidth.
    :
    : The easiest way around this problem is to define your own set
    : procedure, in which you can select which property to update.

    setwidth is protected or private... I can't access it :-(
    why is it wrote like this?
    it should be easier! :(
    now i will have to rewrite my project based in that I can't access random properties with pointers...
    =[

    thanks
  • zibadianzibadian Member Posts: 6,349
    :
    : : Normally access methods are private and the fields of the properties
    : : are always private. In case of a TForm the Width access method
    : : (SetWidth) is private as well, based on D5.
    : : As for pointing to an access method: access methods for non-indexed
    : : properties have this form:
    : : [code]: :
    : : procedure TForm.SetWidth(const value: integer);
    : : [/code]: :
    : : If you want to use pointer to set the width (even if SetWidth() were
    : : protected or more visible), the code would look like this:
    : : [code]: :
    : : type
    : : TSetInt = procedure(const value: integer) of object;
    : :
    : : var
    : : AccessMethod: TSetInt;
    : : begin
    : : TMethod(AccessMethod).Code := Form1.SetWidth;
    : : TMethod(AccessMethod).Data := Form1;
    : : AccessMethod(x);
    : : end;
    : : [/code]: :
    : : The type TSetInt would only work for integer properties, but not for
    : : any other type, even if they are compatible with integer.
    : :
    : : It is also not strange that the ShowMessage() shows the updated
    : : width, because the TForm (defined in TControl) does have a width
    : : field, which is updated. The problem is that windows never is
    : : notified of the new width, which is the task of SetWidth(). The
    : : property width simply returns the field FWidth.
    : :
    : : The easiest way around this problem is to define your own set
    : : procedure, in which you can select which property to update.
    :
    : setwidth is protected or private... I can't access it :-(
    : why is it wrote like this?
    : it should be easier! :(
    : now i will have to rewrite my project based in that I can't access
    : random properties with pointers...
    : =[
    :
    : thanks
    Accessing random properties with pointers is highly dangerous, because some properties don't exist or are read only. For example:
    [code]
    TMyArray = class(TObject)
    private
    FData: array of int;
    function GetLength: integer;
    function GetData(index: integer): integer;
    public
    property Length: integer read GetLength;
    property Data[index: integer]: integer read GetData;
    end;

    function TMyArray.GetLength: integer;
    begin
    Result := Length(FData);
    end;

    function TMyArray.GetData(index: integer): integer;
    begin
    Result := FData[index];
    end;
    [/code]
    Suppose you want to access a random property from TMyArray using pointers:
    [code]
    X := @MyArray.Data;
    [/code]
    X now points to an access method for a read-only dynamic array. The following code will quite possibly make the TMyArray go FUBAR:
    [code]
    X^ := 50;
    [/code]
    The example also includes a property, which doesn't even contain any field of data, but is calculated each time it is accessed. This kind of property cannot be changed at all (except by changing other properties).
    Then there's also the problem of type-casting:
    [code]
    var
    X: pointer;
    begin
    X := Form1.Caption;
    X^ := 50;
    end;
    [/code]
    or even worse:
    [code]
    X := Form1.Width;
    X^ := 'Hello World';
    [/code]
    The last example would not only change the Width, but also the Height and ControlStyle properties, because 'Hello World' is much larger than an integer.
  • tijoentijoen Member Posts: 141

    : Accessing random properties with pointers is highly dangerous,
    : because some properties don't exist or are read only. For example:
    : [code]:
    : TMyArray = class(TObject)
    : private
    : FData: array of int;
    : function GetLength: integer;
    : function GetData(index: integer): integer;
    : public
    : property Length: integer read GetLength;
    : property Data[index: integer]: integer read GetData;
    : end;
    :
    : function TMyArray.GetLength: integer;
    : begin
    : Result := Length(FData);
    : end;
    :
    : function TMyArray.GetData(index: integer): integer;
    : begin
    : Result := FData[index];
    : end;
    : [/code]:
    : Suppose you want to access a random property from TMyArray using
    : pointers:
    : [code]:
    : X := @MyArray.Data;
    : [/code]:
    : X now points to an access method for a read-only dynamic array. The
    : following code will quite possibly make the TMyArray go FUBAR:
    : [code]:
    : X^ := 50;
    : [/code]:
    : The example also includes a property, which doesn't even contain any
    : field of data, but is calculated each time it is accessed. This kind
    : of property cannot be changed at all (except by changing other
    : properties).
    : Then there's also the problem of type-casting:
    : [code]:
    : var
    : X: pointer;
    : begin
    : X := Form1.Caption;
    : X^ := 50;
    : end;
    : [/code]:
    : or even worse:
    : [code]:
    : X := Form1.Width;
    : X^ := 'Hello World';
    : [/code]:
    : The last example would not only change the Width, but also the
    : Height and ControlStyle properties, because 'Hello World' is much
    : larger than an integer.


    Understood
    i already have other way to do it, more work, but will work
    thanks!
Sign In or Register to comment.