VCL DLL 中如何解决 Tab 键不好使的问题?

QPlugins 支持 DLL 插件,但是,插件中的窗体如果要嵌入主窗体的某个控件上,往往会发生一些奇怪的事情,百度 Delphi DLL Form 大约可以搜索到 860,000 个结果,大家给出的解决方案千奇百怪。本文提供的解决方法反而可能是最简单的了。

首先声明一下,这个不是最完美的解决方案,QPlugins 里提供的 qplugins.vcl.pas 提供了更完美的解决办法,但由于是众筹项目,暂时不能开源。在这里为大家提供一种简单但基本完美的解决办法,只所以说它不够完美这是因为:

  • 这里的实现不能跨IDE,必需用同一个编程环境,即 DLL 必需和宿主程序使用同一个版本的 Delphi 编译,当你试图用 XE8 编译的宿主程序来调用 DLL 中的程序时,就可能出现无法预知的问题;
  • DLL 中的 Application 对象相关的属性及方法无效;
  • 其它我还未知的问题;

但这个方法也是相当简单的了,能够满足一般需要了。具体实现步骤如下:

1、在你的主程序中加入下面的代码:

{本源码来自于 QDAC 项目(项目简介:https://blog.qdac.cc/?p=1543),官方网站:www.qdac.cc,作者:swish,您可以免费使用该代码,但必需保留相关的版权信息,如果做出完善,应将完善后的代码反馈给作者}
type
  TVCLCtrlTestHook = class(TComponent)
  protected
    FMsgId: DWORD;
    function DoTest(AHandle: HWND): Boolean;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

{ TVCLCtrlTestHook }

constructor TVCLCtrlTestHook.Create(AOwner: TComponent);
begin
  inherited;
  FMsgId := RegisterWindowMessage(PChar('DelphiRM_GetObjectInstance'));
  IsVCLControlHook := DoTest;
end;

destructor TVCLCtrlTestHook.Destroy;
begin
  IsVCLControlHook := nil;
  inherited;
end;

function TVCLCtrlTestHook.DoTest(AHandle: HWND): Boolean;
begin
  if AHandle <> 0 then
    Result := SendMessage(AHandle, FMsgId, GetCurrentProcessId, 0) <> 0
  else
    Result := False;
end;

2、在你程序的主窗体中创建 TVCLCtrlTestHook 的实例。

procedure TForm1.FormCreate(Sender: TObject);
begin  
  TVCLCtrlTestHook.Create(Self);
end;

好了,你所要做的就是这些。如果你寻求更完美的解决方案,可以参与 QDAC 众筹,从而获得 qplugins.vcl.pas 的源码。qplugins.vcl.pas 源码只需要在宿主程序 和 DLL 中直接引用就可以了,不需要额外的编码。

分享到: