2012-07-02 21 views
5

Tôi đang cập nhật một số thuộc tính trong một thành phần. Để tránh các lỗi thuộc tính bị thiếu Tôi đang sử dụng DefineProperties để đọc các thuộc tính cũ từ luồng. Hầu hết các thuộc tính hoạt động tốt, ví dụ: Số nguyên, nhưng tôi không thể nhận được các thuộc tính dựa trên TPersistent để hoạt động. Thủ tục ReadProperty (TPersistent) trong TReader được bảo vệ, không công khai và yêu cầu phải truy cập vào nó. Thậm chí sau đó, thủ tục ReadFontProperty không bao giờ được gọi và ngoại lệ thuộc tính bị thiếu xảy ra.Sử dụng DefineProperties để thay thế các thuộc tính TPersistent ví dụ: TFont

Làm cách nào để đọc tài sản TFont?

Dưới đây là một số mã mẫu về cách tôi đang cố gắng thực hiện.

... 

type 
    TMyComponent = class(TComponent) 
    strict private 
    // Removed 
    //FIntegerProperty: Integer; 
    //FFontProperty: TFont; 

    // New 
    FNewIntegerProperty: Integer; 
    FNewFontProperty: TFont; 

    procedure ReadIntegerProperty(Reader: TReader); 
    procedure ReadFontProperty(Reader: TReader); 
    protected 
    procedure DefineProperties(Filer: TFiler); override; 
    published 
    // Removed properties 
    //property IntegerProperty: Integer read FIntegerProperty write FIntegerProperty; 
    //property FontProperty: TFont read FFontProperty write SetFontProperty; 

    // New properties 
    property NewIntegerProperty: Integer read FNewIntegerProperty write FNewIntegerProperty; 
    property NewFontProperty: TFont read FNewFontProperty write SetNewFontProperty; 
    end; 

implementation 

procedure TMyComponent.DefineProperties(Filer: TFiler); 
begin 
    inherited; 

    // This works 
    Filer.DefineProperty('IntegerProperty', ReadIntegerProperty, nil, FALSE); 

    // This doesn't 
    Filer.DefineProperty('FontProperty', ReadFontProperty, nil, FALSE); 
end; 

procedure TMyComponent.ReadIntegerProperty(Reader: TReader); 
begin 
    FNewIntegerProperty:= Reader.ReadInteger; 
end; 

type 
    THackReader = class(TReader); 

procedure TMyComponent.ReadFontProperty(Reader: TReader); 
begin 
    { TODO : This doesn't work. How do we read fonts? } 
    THackReader(Reader).ReadProperty(FNewFontProperty); 
end; 

... 

Cập nhật 1

Cố gắng gợi ý của David sử dụng đoạn mã sau:

Filer.DefineProperty('Font.CharSet', ReadFontCharSet, nil, False); 

...

procedure TMyComponent.ReadFontCharSet(Reader: TReader); 
begin 
    Reader.ReadInteger; 
end; 

tôi nhận được một Invalid Property Value lỗi. Tôi đoán đó là điều cần làm với Charset là loại TFontCharset (= System.UITypes.TFontCharset = 0..255). Làm cách nào để đọc loại tài sản này?

Trả lời

4

Để thực hiện việc này, bạn cần phải làm việc với từng thuộc tính được xuất bản riêng lẻ của TFont và bạn sẽ cần phải sử dụng tên đủ điều kiện.

Filer.DefineProperty('FontProperty.Name', ReadFontName, nil, False); 
Filer.DefineProperty('FontProperty.Height', ReadFontHeight, nil, False); 
Filer.DefineProperty('FontProperty.Size', ReadFontSize, nil, False); 
// and so on for all the other published properties of TFont 

ReadFontName, ReadFontHeight vv nên đọc các giá trị tài sản cũ vào thành phần mới được đặt tên.

procedure TMyComponent.ReadFontName(Reader: TReader); 
begin 
    FNewFontProperty.Name := Reader.ReadString; 
end; 

// etc. etc. 

Cập nhật

Bạn hỏi làm thế nào để đọc tài sản Charset. Điều này phức tạp vì nó có thể được viết dưới dạng mã nhận dạng văn bản (xem hằng số FontCharsets trong Graphics.pas) hoặc dưới dạng giá trị số nguyên đơn giản. Dưới đây là một số mã bị tấn công nhanh chóng với nhau sẽ đọc Charset của bạn.

procedure TMyComponent.ReadFontCharset(Reader: TReader); 

    function ReadIdent: string; 
    var 
    L: Byte; 
    LResult: AnsiString; 
    begin 
    Reader.Read(L, SizeOf(Byte)); 
    SetString(LResult, PAnsiChar(nil), L); 
    Reader.Read(LResult[1], L); 
    Result := UTF8ToString(LResult); 
    end; 

    function ReadInt8: Shortint; 
    begin 
    Reader.Read(Result, SizeOf(Result)); 
    end; 

    function ReadInt16: Smallint; 
    begin 
    Reader.Read(Result, SizeOf(Result)); 
    end; 

var 
    Ident: string; 
    CharsetOrdinal: Integer; 

begin 
    Beep; 
    case Reader.ReadValue of 
    vaIdent: 
    begin 
     Ident := ReadIdent; 
     if not IdentToCharset(Ident, CharsetOrdinal) then begin 
     raise EReadError.Create('Could not read MyFont.Charset'); 
     end; 
     FNewFontProperty.Charset := CharsetOrdinal; 
    end; 
    vaInt8: 
    FNewFontProperty.Charset := ReadInt8; 
    vaInt16: 
    FNewFontProperty.Charset := ReadInt16; 
    else 
    raise EReadError.Create('Could not read FontProperty.Charset'); 
    end; 
end; 
+0

@norgepaul Bạn đã tham gia bằng cách nào? Tôi khá chắc chắn đó là câu trả lời cho câu hỏi của bạn. –

+0

Xin chào David. Cảm ơn câu trả lời. Tôi chắc chắn nó là chính xác, nhưng tôi đã không có cơ hội để kiểm tra nó được nêu ra. Tôi sẽ cố gắng để có được nó sớm. – norgepaul

+0

OK, tôi chỉ tự hỏi liệu bạn có gặp vấn đề và tò mò không. –

Các vấn đề liên quan