自定义控件打破包之间的可视窗体继承

时间:2013-05-29 20:29:48

标签: delphi package delphi-xe2 subclass

我正在使用Delphi XE2(Update 3)。我有一个非常大的项目,在编译包时有时会崩溃Delphi IDE。我已经能够将其拆分为一个复制问题的简单项目。

问题摘要

当您使用VCL框架在包之间进行可视化表单继承并且祖先框架包含标准控件时,一切正常。

当你做同样的事情时,除了用控件的子类替换祖先框架中的标准控件之外,你就可以轻易地崩溃Delphi IDE。

您需要做的就是在设计模式中查看VCL框架时编译包含祖先框架的包,该框架是另一个包的成员,其中VCL框架从祖先框架下降/继承有一个分类控制。

我尝试过对TClientDataSetTEdit进行子类化。两者都表现出相同的行为。

问题

可以使用标准控件时,为什么无法在包之间进行视觉表单继承时使用子类控件?

重现问题的步骤:

  1. 创建一个可以保存所有项目文件的文件夹
  2. 为文件夹中的每个五个文件创建文件
  3. 启动Delphi&关闭所有文件
  4. 点击"文件|新的|其他|德尔福项目|包"
  5. 将程序包保存在步骤1的文件夹中作为' Package1'
  6. CDS2.pas添加到Package1
  7. 构建Package1(添加建议的包)
  8. 安装Package1(将注册TMyCDS)
  9. BaseForm.pas添加到Package1(添加建议的VCL框架)
  10. 构建Package1(添加建议的包),再次构建
  11. 右键单击ProjectGroup1,然后选择"添加新项目|德尔福项目|包"
  12. 将新包保存在步骤1的文件夹中作为' Package2'
  13. SecondFrame.pas添加到Package2(添加建议的VCL框架)
  14. 构建Package2(添加建议的包)
  15. 在设计模式下查看SecondFrame(例如,按F12)
  16. 保存所有更改(包括项目组,因为Delphi即将崩溃)
  17. 在设计模式下查看SecondFrame时,请构建 Package1
  18. 构建失败,我收到此错误:

    [DCC Error] E2161 Error: RLINK32: Error opening file "C:\[folder]\BaseFrame.dfm"
    

    如果我在步骤17中编译而不是构建,它通常会编译而不会出错。但是,有时当我尝试在设计模式下重新显示SecondFrame时,我收到此错误:

    Access violation at address 5003C976 in module 'rtl160.bpl'. Read of address FFFFFFC4.
    
    [5003C976]{rtl160.bpl  } System.GetDynaMethod (Line 13480, "System.pas" + 7) + $0
    [500ADE1D]{rtl160.bpl  } System.Classes.IsDefaultObjectProp (Line 9525, "System.Classes.pas" + 9) + $B
    [500AE2C1]{rtl160.bpl  } System.Classes.IsDefaultPropertyValue (Line 9651, "System.Classes.pas" + 29) + $A
    [500AECA7]{rtl160.bpl  } System.Classes.TWriter.WriteProperty (Line 9893, "System.Classes.pas" + 12) + $7
    [5044739A]{vcl160.bpl  } Vcl.Forms.TScrollingWinControl.IsTouchPropertyStored (Line 3200, "Vcl.Forms.pas" + 1) + $4
    [503432C6]{vcl160.bpl  } Vcl.Controls.TCustomTouchManager.IsTabletOptionsStored (Line 17359, "Vcl.Controls.pas" + 1) + $9
    [500AE08D]{rtl160.bpl  } System.Classes.IsDefaultMethodProp (Line 9606, "System.Classes.pas" + 4) + $4
    [500AE0ED]{rtl160.bpl  } System.Classes.IsDefaultMethodProp (Line 9609, "System.Classes.pas" + 7) + $24
    [500AE2CC]{rtl160.bpl  } System.Classes.IsDefaultPropertyValue (Line 9653, "System.Classes.pas" + 31) + $A
    [5033A7E9]{vcl160.bpl  } Vcl.Controls.TWinControl.GetChildren (Line 12359, "Vcl.Controls.pas" + 1) + $3
    [5003C9A6]{rtl160.bpl  } System.@CallDynaInst (Line 13519, "System.pas" + 4) + $0
    [50447AE1]{vcl160.bpl  } Vcl.Forms.TCustomFrame.GetChildren (Line 3450, "Vcl.Forms.pas" + 6) + $6
    [500AD658]{rtl160.bpl  } System.Classes.TWriter.WriteData (Line 9270, "System.Classes.pas" + 54) + $2
    [500B4423]{rtl160.bpl  } System.Classes.TComponent.ValidateRename (Line 12845, "System.Classes.pas" + 0) + $F
    [500AD317]{rtl160.bpl  } System.Classes.TWriter.WriteComponent (Line 9200, "System.Classes.pas" + 20) + $9
    [500AD761]{rtl160.bpl  } System.Classes.TWriter.WriteFloat (Line 9298, "System.Classes.pas" + 1) + $3
    [20FEC1AB]{designide160.bpl} ComponentDesigner.TComponentRoot.CreateRootInstance (Line 2288, "ComponentDesigner.pas" + 24) + $7
    [20FEBFD7]{designide160.bpl} ComponentDesigner.TComponentRoot.CreateRootAs (Line 2255, "ComponentDesigner.pas" + 2) + $4
    [20FEBEFA]{designide160.bpl} ComponentDesigner.TComponentRoot.CreateFromStream (Line 2235, "ComponentDesigner.pas" + 7) + $9
    [20FEEF41]{designide160.bpl} ComponentDesigner.TComponentRoot.Resurrect (Line 3434, "ComponentDesigner.pas" + 11) + $6
    [2104F16E]{designide160.bpl} EmbeddedDesignerForm.TFormEditorView.Display (Line 144, "EmbeddedDesignerForm.pas" + 4) + $5
    [2075E399]{coreide160.bpl} EditorForm.TEditWindow.ShowView (Line 4294, "EditorForm.pas" + 49) + $F
    [20758D44]{coreide160.bpl} EditorForm.TEditWindow.SwitchViews (Line 2147, "EditorForm.pas" + 6) + $9
    [2075889A]{coreide160.bpl} EditorForm.TEditWindow.ViewBarChange (Line 1996, "EditorForm.pas" + 2) + $1
    [504C0F8D]{vcl160.bpl  } Vcl.Tabs.TTabSet.CanChange (Line 1910, "Vcl.Tabs.pas" + 3) + $9
    [504C0FDE]{vcl160.bpl  } Vcl.Tabs.TTabSet.SetTabIndex (Line 1921, "Vcl.Tabs.pas" + 5) + $0
    [504C126A]{vcl160.bpl  } Vcl.Tabs.TTabSet.MouseDown (Line 2033, "Vcl.Tabs.pas" + 6) + $2
    [50332E54]{vcl160.bpl  } Vcl.Controls.TControl.DoMouseDown (Line 7343, "Vcl.Controls.pas" + 7) + $2B
    [50332EA3]{vcl160.bpl  } Vcl.Controls.TControl.WMLButtonDown (Line 7354, "Vcl.Controls.pas" + 7) + $E
    [5033280D]{vcl160.bpl  } Vcl.Controls.TControl.WndProc (Line 7204, "Vcl.Controls.pas" + 91) + $6
    [5033715B]{vcl160.bpl  } Vcl.Controls.TWinControl.WndProc (Line 9976, "Vcl.Controls.pas" + 152) + $6
    [5003D4F7]{rtl160.bpl  } System.TMonitor.TryEnter (Line 14786, "System.pas" + 10) + $0
    [5003D06C]{rtl160.bpl  } System.TMonitor.Enter (Line 14489, "System.pas" + 4) + $2
    [5003CF10]{rtl160.bpl  } System.TMonitor.CheckOwningThread (Line 14411, "System.pas" + 2) + $0
    [5003D216]{rtl160.bpl  } System.TMonitor.Exit (Line 14600, "System.pas" + 9) + $7
    [5003D24F]{rtl160.bpl  } System.TMonitor.Exit (Line 14614, "System.pas" + 2) + $7
    [50313627]{vcl160.bpl  } Vcl.Graphics.FreeMemoryContexts (Line 7043, "Vcl.Graphics.pas" + 12) + $8
    [503367B0]{vcl160.bpl  } Vcl.Controls.TWinControl.MainWndProc (Line 9689, "Vcl.Controls.pas" + 3) + $6
    [503367C5]{vcl160.bpl  } Vcl.Controls.TWinControl.MainWndProc (Line 9692, "Vcl.Controls.pas" + 6) + $0
    [503369F0]{vcl160.bpl  } Vcl.Controls.TWinControl.IsControlMouseMsg (Line 9753, "Vcl.Controls.pas" + 9) + $25
    [5033715B]{vcl160.bpl  } Vcl.Controls.TWinControl.WndProc (Line 9976, "Vcl.Controls.pas" + 152) + $6
    [503367B0]{vcl160.bpl  } Vcl.Controls.TWinControl.MainWndProc (Line 9689, "Vcl.Controls.pas" + 3) + $6
    [500B6030]{rtl160.bpl  } System.Classes.MakeObjectInstance (Line 13921, "System.Classes.pas" + 0) + $0
    [504525E7]{vcl160.bpl  } Vcl.Forms.TApplication.ProcessMessage (Line 10164, "Vcl.Forms.pas" + 23) + $1
    [5045262A]{vcl160.bpl  } Vcl.Forms.TApplication.HandleMessage (Line 10194, "Vcl.Forms.pas" + 1) + $4
    [5045295D]{vcl160.bpl  } Vcl.Forms.TApplication.Run (Line 10331, "Vcl.Forms.pas" + 26) + $3
    

    无论发生什么错误,当你尝试做其他任何事情时,Delphi会抛出各种随机访问冲突。我在解除错误后关闭了Delphi。然后我使用任务管理器杀死BDS.EXE(以避免许多额外的A / V错误)。

    我尝试按如下方式调试Delphi:

    调试:

    1. 重启德尔福
    2. 确保SecondFrame未打开
    3. 删除/重新安装Package1并重建它
    4. 双击Package1,使其成为活动项目
    5. 将调试主机应用程序设置为Delphi( C:\ [path] \ RAD Studio \ 9.0 \ bin \ bds.exe
    6. 使用debug(F9)
    7. 运行Package1
    8. Delphi第二次打开后(在第二个实例中)确保您的项目组已打开,然后打开SecondFrame
    9. 确保SecondFrame处于设计模式(例如,按F12),然后编译 Package1
    10. 有时Delphi的第一个实例会捕获在第二个实例中引发的异常,有时候它会赢。如果是这样,异常和堆栈跟踪如下所示:

      First chance exception at $5003C97D. Exception class $C0000005 with message 'access violation at 0x5003c97d: read of address 0x00000001'. Process bds.exe (8912)
      
      :5003c97d GetDynaMethod + $D
      :20fd45a6 TPairings.AddChildren + $46
      :20fd4351 TPairing.SetComponent + $2D
      :20fed656 TComponentRoot.GetRootStream + $5E
      :20ff9d26 TRootStream.Create + $7A
      :20ff2704 TComponentRoot.FormFileOpen + $14
      :21b4231b ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\delphicoreide160.bpl
      :204e7a1e ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\coreide160.bpl
      :20614f2f ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\coreide160.bpl
      :206150f9 ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\coreide160.bpl
      :20615173 ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\coreide160.bpl
      :066d1339 ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\dcc32160.dll
      :1ac81dea ; C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\bin\RLINK32.DLL
      :2a242a24
      


      以下是上面重现问题的步骤中使用的5个文件:

      BaseFrame.dfm

      object BaseFrameClass: TBaseFrameClass
        Left = 0
        Top = 0
        Width = 320
        Height = 240
        TabOrder = 0
        object MyCDS1: TMyCDS
          Aggregates = <>
          Params = <>
          Left = 8
          Top = 8
        end
      end
      

      BaseFrame.pas

      unit BaseFrame;
      
      interface
      
      uses
        Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
        Vcl.Graphics, Vcl.Controls, Vcl.Forms, Data.DB, Datasnap.DBClient, CDS2;
      
      type
        TBaseFrameClass = class(TFrame)
          MyCDS1: TMyCDS;
        end;
      
      implementation
      
      {$R *.dfm}
      
      end.
      

      CDS2.pas

      unit CDS2;
      
      interface
      
      uses
        System.SysUtils, System.Classes, Data.DB, Datasnap.DBClient;
      
      type
        TMyCDS = class(TClientDataSet)
        end;
      
      procedure Register;
      
      implementation
      
      procedure Register;
      begin
        RegisterComponents('Test', [TMyCDS]);
      end;
      
      end.
      

      SecondFrame.dfm

      inherited SecondFrameClass: TSecondFrameClass
      end
      

      SecondFrame.pas

      unit SecondFrame;
      
      interface
      
      uses
        Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
        Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, BaseFrame, Data.DB, Datasnap.DBClient, CDS2;
      
      type
        TSecondFrameClass = class(TBaseFrameClass)
        end;
      
      implementation
      
      {$R *.dfm}
      
      end.
      

1 个答案:

答案 0 :(得分:0)

我在Delphi XE2上安装DSPack时遇到了困难。我会发誓这是在约会。然而,在获得AV后我尝试了很多方法来解决它。

在我看到你的问题后,我终于解决了这个问题,这个问题让我想到继承正在弄乱它。首先,我将所有内容从基础包移动到设计页面,然后从项目组中删除了基本包,编译并安装。工作正常。