在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Delphi中DLL的消息处理 事情的导火线是GIF图片的显示. 在应用程序中, 利用三方的GIFImage.pas可以很好的显示GIF图片. 怪了: GIF图片显示是静态的. 还以为Delphi又出Bug了. 于是又把图片放到程序主窗体上一运行, 动的. 这下头可大了! 找相关的资料, 没有. 看来事情还得自己解决: 于是专心研究起GIFImage.pas, 首先看的当然是重画部分的代码了( 呵呵, 这是我一贯的风格: 觉得是哪里出问题就先看哪里, 不管是谁的代码 ). 经过一番搜索. 把目标定位在线程上. GIFImage.pas的重画其实就是调用一个线程, 在线程内读取文件中相应的图像数据画到目标位置. 在线程内重画是调用线程的Synchronize过程. 以前知道这个过程是为了避免多个线程同时访问同一个数据或对象的. 现在得对它的执行方法做一番了解才行. 经过一翻摸索, 找到了解决方法. 在DLL的窗体上放一个TTimer控件. Interval尽量小. OnTimer只添加一行代码: CheckSynchronize; 运行. OK. 图片动起来了......( 这种方法所存的问题就不用再多说了吧. )
但接下来的一个问题却很恼火的: 在DLL的窗体上放一个TSpeedButton控件, Flat属性设置为True. 运行. 当鼠标从TSpeedButton上移过时, TSpeedButton怎么也还原不了. 试着调用它的重画等功能. 全部没用. 好几天的时间一直在思考这个问题. 后来在处理应用程序的消息的时候, 突然想到: DLL虽然有自己Application, 但它并没有自己的消息循环, 而线程的Synchronize不能执行, TSpeedButton不能还原都是因为有些消息没有得到相应的处理而导致的. 也就是说, 只要给DLL加上一个消息循环, 上面的这些问题都会全部解决. 刚开始的时候想从主程序发送消息给DLL. 可消息截取的结果是: 很多DLL里产生的消息并没有发送给主程序. 看来这个方法是行不通的. 只得另寻方法. 在看到以下几行大家很熟悉的代码后想到. 动手实验, 创建一个DLL, DLL里包含一个窗体DLLForm. 从DLL里导出一个函数. 加上上面的代码. 如下: 不过, 问题又来了. 程序退出时报异常了. 想一下, 哦. DLL里的窗体资源还没有释放呢. 得, 再从DLL里导出一个过程, 代码如下: procedure DestoryDLL; stdcall; var i: Integer; begin for i := Application.ComponentCount - 1 downto 0 do begin if Application.Components[i].ClassNameIs('TDLLChildForm') then begin TDLLChildForm(Application.Components[i]).Release; end; end; if DLLForm = nil then begin Exit; end; DLLForm.Release; DLLForm := nil; end;
再给主程序主窗体的OnCloseQuery添加代码如下: procedure DestoryDLL; stdcall; var i: Integer; begin for i := Application.ComponentCount - 1 downto 0 do begin if Application.Components[i].ClassNameIs('TDLLChildForm') then begin TDLLChildForm(Application.Components[i]).Release; end; end; if DLLForm = nil then begin Exit; end; DLLForm.Release; // Application.Terminate; PostMessage(Application.Handle, WM_QUIT, 0, 0); DLLForm := nil; end;
运行. OK. 完美解决... procedure InitDLL(AHandle: Thandle); stdcall; begin Application.Initialize; Application.ShowMainForm := False; Application.CreateForm(TDLLForm, DLLForm); // 保存原来的句柄 DLLForm.Tag := Application.Handle; // DLL 从属的句柄 ( 如果没有此行, 线程的执行不能达到理想效果 ) // 并且这样才能真正的让消息循环处理它应处理的所有消息 Application.Handle := AHandle; Application.Run; Application.Handle := DLLForm.Tag; end;
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论