TPanelEx = Class(TPanel)
在TPandelEx中我又增加了一个属性叫
property Items: TStringList read GetItems write SetItems;
作用是在TPanelEx上把Items中的字符显示出来
在设计和程序运行中都已经可以动态添加并显示Items中的内容了,
现在的问题是,我在设计时在Items中添加了的字串,在程序执行时无法显示,只能在程序运行时动态添加.查了一下类似的TListBox,也没有得到答案.

解决方案 »

  1.   

    你必須自己實現編繹器的流化, 印象中, 故國的那本書 <<delphi 精要>> 就有說到
      

  2.   

    参考TPanel 的源码,看看Caption是怎么画出来的!
      

  3.   

    在SetItems中,加一句Caption := FItems.Text;
    或者继承绘制过程,先调用Caption := FItems.Text;再inherited试试
      

  4.   

    FItems在设计时的内容我写的是
    '123'
    '456'
    可程序运行时,FItems中什么都有没有,也就是说TPanelEx在Create的时候没有载入我设计时写的内容.我想这应该是要我手动完成的,可是如何实现呢?
      

  5.   

    在设计期,FORM右键菜单VIEW AS TEXT显示内容是怎么样的?
      

  6.   

    FORM右键菜单VIEW AS TEXT显示内容应该没有您添加的,也就是说可能没有做保存;如果没有的话,你可以在创建你的类的时候指定一下它的parent;
    如果有,那么可能是你创建的时候没有载入你的属性;
      

  7.   

    你的问题是在设计时输入的字符串在设计时丢掉了还是设计时输入的字符串画不出来?
    如果是前者,在D7的源码中有好多例子,如TMemo,TComBox,TTabSet...等.
      

  8.   

    如上所说,我也找了一些看TListBox,TMemo
    当时我挑了一个TMemo,粗看了它的代码,没有找到问题的根源.
    然后细看了TCustomMemo.Create()
    constructor TCustomMemo.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Width := 185;
      Height := 89;
      AutoSize := False;
      FWordWrap := True;
      FWantReturns := True;
      FLines := TMemoStrings.Create;
      TMemoStrings(FLines).Memo := Self;
      ParentBackground := False;
    end;
    涉及FLines的只有两句
      FLines := TMemoStrings.Create;
      TMemoStrings(FLines).Memo := Self;
    事实上也看不出有什么玄妙的.甚至找不到TMemoStrings或TStrings的Create函数,还请高手指点.手把手的教一下.呵呵
      

  9.   

    现在代码不在手中,给个大概的情况吧
    TPanelEx = Class(TPanel)
      private
        FLines: TStrings;
        function GetLines(): TStrings;
        procedure SetLines(const Value: TStrings);
      protected
        procedure Paint;override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property Items: TStrings read GetLines write SetLines;
      end;
    constructor TPanelEx.Create(AOwner: TComponent); override;
    begin
      FLines := TStringList.Create;//这里比较偷懒,没有从TStrings中派生出一个而是直接用了一个现成的
      
    end;
    procedure Paint;override
    begin
      在PanelEx上把Flines中的字符显示出来
    end;
    function GetLines():TStrings;
    begin
      {Result := TStringList.Create
       Result.assign(FLines)}
    end;
    事实上,我在设计时,在Object Inspect中的Items中写入
    '123'
    '1234'
    在PanelEx1上是可以显示出来的
    同样,如果我在程序中
    ss := TStringList.Create;
    ss.add('123');
    ss.add('1234');
    PanelEx1.Items := ss;
    也是可以显示出来的,但是我在设计时写入的
    '123'
    '1234'
    在程序运行时就无法显示了,FLines里面是空的。
    可能正如 aiirii(ari-爱的眼睛) 所说的没有实现流话,请问如何实现呢?
      

  10.   

    没看到点子上!!!
    查看 StdCtrls.Pas中TMemoStrings的声明和实现:
    TMemoStrings = class(TStrings)
      private
        Memo: TCustomMemo;
      protected
        function Get(Index: Integer): string; override;
        function GetCount: Integer; override;
        function GetTextStr: string; override;
        procedure Put(Index: Integer; const S: string); override;
        procedure SetTextStr(const Value: string); override;
        procedure SetUpdateState(Updating: Boolean); override;
      public
        procedure Clear; override;
        procedure Delete(Index: Integer); override;
        procedure Insert(Index: Integer; const S: string); override;
      end;
    { TMemoStrings }function TMemoStrings.GetCount: Integer;
    begin
      Result := 0;
      if Memo.HandleAllocated or (Memo.WindowText <> nil) then
      begin
        Result := SendMessage(Memo.Handle, EM_GETLINECOUNT, 0, 0);
        if SendMessage(Memo.Handle, EM_LINELENGTH, SendMessage(Memo.Handle,
          EM_LINEINDEX, Result - 1, 0), 0) = 0 then Dec(Result);
      end;
    end;function TMemoStrings.Get(Index: Integer): string;
    var
      Text: array[0..4095] of Char;
    begin
      Word((@Text)^) := SizeOf(Text);
      SetString(Result, Text, SendMessage(Memo.Handle, EM_GETLINE, Index,
        Longint(@Text)));
    end;procedure TMemoStrings.Put(Index: Integer; const S: string);
    var
      SelStart: Integer;
    begin
      SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index, 0);
      if SelStart >= 0 then
      begin
        SendMessage(Memo.Handle, EM_SETSEL, SelStart, SelStart +
          SendMessage(Memo.Handle, EM_LINELENGTH, SelStart, 0));
        SendMessage(Memo.Handle, EM_REPLACESEL, 0, Longint(PChar(S)));
      end;
    end;procedure TMemoStrings.Insert(Index: Integer; const S: string);
    var
      SelStart, LineLen: Integer;
      Line: string;
    begin
      if Index >= 0 then
      begin
        SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index, 0);
        if SelStart >= 0 then Line := S + #13#10 else
        begin
          SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index - 1, 0);
          if SelStart < 0 then Exit;
          LineLen := SendMessage(Memo.Handle, EM_LINELENGTH, SelStart, 0);
          if LineLen = 0 then Exit;
          Inc(SelStart, LineLen);
          Line := #13#10 + s;
        end;
        SendMessage(Memo.Handle, EM_SETSEL, SelStart, SelStart);
        SendMessage(Memo.Handle, EM_REPLACESEL, 0, Longint(PChar(Line)));
      end;
    end;procedure TMemoStrings.Delete(Index: Integer);
    const
      Empty: PChar = '';
    var
      SelStart, SelEnd: Integer;
    begin
      SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index, 0);
      if SelStart >= 0 then
      begin
        SelEnd := SendMessage(Memo.Handle, EM_LINEINDEX, Index + 1, 0);
        if SelEnd < 0 then SelEnd := SelStart +
          SendMessage(Memo.Handle, EM_LINELENGTH, SelStart, 0);
        SendMessage(Memo.Handle, EM_SETSEL, SelStart, SelEnd);
        SendMessage(Memo.Handle, EM_REPLACESEL, 0, Longint(Empty));
      end;
    end;procedure TMemoStrings.Clear;
    begin
      Memo.Clear;
    end;procedure TMemoStrings.SetUpdateState(Updating: Boolean);
    begin
      if Memo.HandleAllocated then
      begin
        SendMessage(Memo.Handle, WM_SETREDRAW, Ord(not Updating), 0);
        if not Updating then
        begin   // WM_SETREDRAW causes visibility side effects in memo controls
          Memo.Perform(CM_SHOWINGCHANGED,0,0); // This reasserts the visibility we want
          Memo.Refresh;
        end;
      end;
    end;function TMemoStrings.GetTextStr: string;
    begin
      Result := Memo.Text;
    end;procedure TMemoStrings.SetTextStr(const Value: string);
    var
      NewText: string;
    begin
      NewText := AdjustLineBreaks(Value);
      if (Length(NewText) <> Memo.GetTextLen) or (NewText <> Memo.Text) then
      begin
        if SendMessage(Memo.Handle, WM_SETTEXT, 0, Longint(NewText)) = 0 then
          raise EInvalidOperation.Create(SInvalidMemoSize);
        Memo.Perform(CM_TEXTCHANGED, 0, 0);
      end;
    另TComboBox,TTabSet等也有类似的实现,这是关键!
      

  11.   

    不知道我理解的对不对,
    Memo间接继承自CustermEdit,它的Lines直接是来自CustermEdit的Text.这样是每个Edit天生就有的,而我的PanelEx是增加了一个全新的,Items的属性,没法子从其它属性中取值.
    还有,我拿原生类型试试,Integer,String,设计和运行时都是没有问题的,请高手们继续.
      

  12.   

    给你我测试的代码吧:
    unit PanelEx;interfaceuses
      SysUtils, Classes, Controls, ExtCtrls;type
      TPanelEx = class;
      TItemList = class(TStringList)
      private
        Panel: TPanelEx;
      public
        procedure Insert(Index: Integer; const S: string); override;
        procedure Delete(Index: Integer); override;
        function  Add(const S: string): Integer; override;
      end;  TPanelEx = class(TPanel)
      private
        { Private declarations }
        FItems : TStrings;
        procedure SetItemList(Value: TStrings);
      protected
        { Protected declarations }
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        { Published declarations }
        property items: TStrings read FItems  write SetItemList;
      end;procedure Register;implementationprocedure Register;
    begin
      RegisterComponents('Samples', [TPanelEx]);
    end;{ TOWNTabList }function TItemList.Add(const S: string): Integer;
    begin
      Result := inherited Add(S);end;procedure TItemList.Insert(Index: Integer; const S: string);
    begin
      inherited Insert(Index, S);
    end;procedure TItemList.Delete(Index: Integer);
    begin
      inherited Delete(Index);
    end;{TPanelEx}
    constructor TPanelEx.Create(AOwner: TComponent);
    begin
         inherited Create(AOwner);
         FItems := TItemList.Create;
         TItemList(FItems).Panel := Self;
    end;
    destructor TPanelEx.Destroy;
    begin
         FItems.Free;
    end;
    procedure TPanelEx.SetItemList(Value: TStrings);
    begin
         FItems.Assign(Value); 
    end;
    end.
      

  13.   

    自定义的StringList属性,需要你自己去维护的,偷懒是不行的,嗬嗬,
    原因,我也说不清楚。感觉好像设计时字符串是由TItemList 来维护的,要不,
    你在运行赋给的字符串岂不在设计时也看见了?直接调用TStringList应该不能(或
    是编译器不允许)完成保存字符串的功能。
      

  14.   

    楼上的代码我试试,确实能用,在设计时的字符串在使用的已经可见.不过有个小错误
    destructor TPanelEx.Destroy;
    begin
         FItems.Free;
         这里应该加一句inherited,否则会报错,不过无伤大
    end;问题刚刚找到了,如果是这样
    property Items: TStrings read GetItems write SetItems;
    GetItems反回的是一个FItems的副本.
    不行
    property Items: TStrings read FItems write SetItems;
    就行了.