DLL封装子窗体的老问题,新的解决方案,一起来探讨(100)

  • 主题发起人 summer_core99
  • 开始时间
S

summer_core99

Unregistered / Unconfirmed
GUEST, unregistred user!
我也是照着这样做的,可是还是cannot assign a TFont to a TFont。向Dll中传入Screen后,如果子窗体有Toolbar或StatusBar,那铁定出现cannot assign a TFont to a TFont,这使得不相带包编译,又想充分利用Screen对象都无法实现,以下是鬼佬的一个方法,我搞了,不行,不知哪里出了问题====================================================================经验共享: 主程序调用DLL窗体 cannot assign a TFont to a TFont 问题的彻底解决方案 在网上搜索N久,总结并实战出来的经验和大家分享 1、中国的网站链接大多建议的方案是 project-
1​
options选项的packages标签页面勾选 'Buidl with runtime packages' 我个人在D7中测试确实能够解决问题。但是程序发布的时候需要带很多bpl包。 2、在国外网站搜索到另一种解决方案,就是通过修改系统的controls.pas和graphics.pas两个文件来彻底解决上述问题。 具体链接地址为:http://tengco.spaces.live.com/Blog/cns!689EE398F7BFBE58!150.entry http://www.delphi3000.com/articles/article_4957.asp?SK= 下面是我的程序做法: 首先、把系统的controls.pas和graphics.pas拷贝到自己的工程目录,并做如下修改 第一步、在controls.pas 的声明部分加入 function GetControlAtom : pointer; 第二步、在controls.pas 的实现部分加入 function GetControlAtom : pointer; begin result := @ControlAtom; end; 第三步、修改graphics.pas的TCanvas.SetFont函数 procedure TCanvas.SetFont(Value: TFont); begin FFont.Assign(Value); end; 给上面的代码加上 try..except保护,编程如下: procedure TCanvas.SetFont(Value: TFont); begin try FFont.Assign(Value); except on Exception do; end; end; 第四步、在DLL工程中引入我们修改好的两个文件; 第五步、DLL工程的初始化 procedure myDllProc(dWseason: DWORD); var p:^word; begin case dWseason of DLL_PROCESS_ATTACH: begin oldApp := Application; //保存DLL的Application oldScr := Screen; //保存DLL的Screen p := Controls.GetControlAtom; OldControlAtom := p^; CoInitialize(nil); //使用了ADO控件所以需要调用此方法 end; DLL_PROCESS_DETACH: begin p := Controls.GetControlAtom; p^ := OldControlAtom; application := oldApp; //恢复Dll的Application Screen := oldScr; //恢复Dll的Screen CoUninitialize(); //使用了ADO控件所以需要调用此方法 end; end; end; procedure InitDll(var app:tapplication; var scr:Tscreen; RealControlAtom:integer); var p:^word; begin p := controls.GetControlAtom; if scr
1​
1​
nil then screen := scr; application := app; p^ := RealControlAtom; end; library testdll; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses ShareMem, SysUtils, Classes, windows, Controls in 'Controls.pas', Graphics in 'Graphics.pas'; exports InitDll; begin DllProc := @myDllProc; myDllProc(DLL_PROCESS_ATTACH); //DLL入口初始化 end. 主程序调用示例: ... p := controls.GetControlAtom; InitDll(application,screen,p^);
 
我以前在做DLL时,也老是出现:cannot assign a TFont to a TFont如果按你的方法不带BPL,对是否可行?交流或讨论,我的QQ:165441494 EMail:Delphi2005@163.com
 
改VCL也是治标不治本,可以把cannot assign的错误去掉,但还是会陆续有其他问题。只有两个彻底解决办法:一、带包编译二、使用标准接口,不要传VCL对象之类的。
 
来自:xianjun, 时间:2010-5-6 9:59:46, ID:3992621 改VCL也是治标不治本,可以把cannot assign的错误去掉,但还是会陆续有其他问题。只有两个彻底解决办法:一、带包编译二、使用标准接口,不要传VCL对象之类的。 ==========================标准接口?
 
符合Windows API标准的接口参数传递。
 
就是只传句柄,Pchar这些之类的是吧,这样被其实语言来调用也可以调用得出来吧?这是可行,但是会失去焦点,统计不了子窗体之类的问题
 
我赞成summer_core99的方法,毕竟做系统首先是稳定可靠,其它都有是第二位的!
 
可以通用,又稳定最好
 
第一种方法改VCL的源码,部分三方控件仍然会报这个错,这就存在某种取舍。第二种方法带运行时包,不会有任何问题。总结:建议用带运行时包的方式。
 
不传对象,接口都符合WINDOWS API标准,有时候,这很难做到。
 
想要让C#调用Delphi DLL封装的窗体
 
有一个例子:以前做的测试。试一下吧!好像没有你说的问题!delphi7编译http://www.pudn.com/downloads115/sourcecode/delphi_control/detail484887.html#
 
传Screen是有这个现象的
 
期待高人
 
改为带包运行最好的方法,只需发布rtl和vcl即可。我已经把他们打包成一个BPL文件。使用没有什么不方便的。
 
直接改classes.pas可以把这些错误避免掉,程序能正常运行但还是有其他一些问题不带包发布,总会有这样那样的问题。
 
我将窗体封装在DLL中,并设置了皮肤,在窗体调用时皮肤却显示不出来,那位能帮忙
 
顶部