如何在 dll 窗体中显示背景图像并将面板居中?

How display a background image and center a panel in a dll Form?

我想加载一个图像,作为保留在 dll 中的最大化窗体的背景。

dll 是从 Vcl Form 应用程序调用的,但在无法在 Form 上加载背景图像时遇到问题,dll 总是崩溃。

谢谢你的帮助。

============================================= ==============================

可执行文件

unit Unit2;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  end;

var
  Form2: TForm2;

implementation  {$R *.dfm}

procedure LoadDLL;
type
  TShowformPtr = procedure; stdcall;
var
  HDLL: THandle;
  Recv: TShowformPtr;
begin
  HDLL := LoadLibrary('lib.dll');
  if HDLL <> 0 then
  begin
    @Recv := GetProcAddress(HDLL, 'Recv');
    if @Recv <> nil then
    Recv;
  end;
  //FreeLibrary(HDLL);
end;

procedure TForm2.btn1Click(Sender: TObject);
begin
LoadDLL;
end;

end.

Dll

主要:

library Project2;
uses
  SysUtils, Classes, Unit1, Unit2;

{$R *.res}

procedure Recv; stdcall;
begin
  showform;
end;

exports
  Recv;

begin
end.

Unit1(表格):

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    img1: TImage;
    pnl1: TPanel;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    procedure CreateParams(var Params: TCreateParams); override;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
   Params.WndParent:= Application.Handle;
  Params.ExStyle := Params.ExStyle or WS_EX_TOPMOST or WS_EX_TRANSPARENT;
  Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  brush.Style := bsclear;
  img1.Picture.LoadFromFile(IncludeTrailingBackslash(GetCurrentDir) + 'background.bmp');
  SetWindowPos(Form1.handle, HWND_TOPMOST, Form1.Left, Form1.Top, Form1.Width,
    Form1.Height, 0);

  ShowWindow(Application.handle, SW_HIDE);

  pnl1.Top := (self.Height div 2) - (pnl1.Height div 2);
  pnl1.Left := (self.Width div 2) - (pnl1.Width div 2);
end;

end.

第2单元:

unit Unit2;

interface

Uses
  windows,
  Unit1,
  SysUtils;

  procedure showform;

implementation

procedure showform;
begin
  Form1 := TForm1.Create(Form1);
  sleep(100);
  Form1.Show;
  Form1.Pnl1.Visible := True;
end;

end.

你的问题问题比较多,考虑到不够详细,我尽量回答。

  1. 您正在使用表单,因此您正在构建 VCL 应用程序。您需要让 IDE 将 VCL 框架分配给您的项目。

  2. 这一行错得离谱:

    Form1 := TForm1.Create(Form1);  
    

    rare circumstances show a from own itself. I would go and say that most probably this is why your application crashes. See this 中了解有关 DLL 中表单的详细信息。

    如果您不能正确调试您的应用程序,请在该行之前和之后发出一声蜂鸣声(在它们之间进行延迟)。

  3. 我觉得你的问题应该叫"how to debug a Delphi project".

    您需要做的是获取程序崩溃的确切行。这将使您深入了解为什么会出现 error/crash(顺便说一下,您从未显示过确切的错误消息)。

    去检查 HadShi (recommended) or EurekaLog (buggy) or Smartinspect (I never tried it. Price is similar to the other two). Make sure that you are running in debug mode, the Integrated debugger is on (see IDE options) and that the debug information is present 在你的 EXE/DLL.

    PS:您仍然可以在没有上面显示的三个记录器之一的情况下调试您的应用程序。只需在调试模式下将您的项目正确配置为 运行!

    要调试 DLL,请参阅 'Run->Parameters' 菜单。在那里定义一个 host 应用程序,它将加载您的 DLL。如果错误是 DLL,调试器将控制并将光标置于产生崩溃的代码行。

  4. 不知道你最终purpose/what想达到什么目的。因此,我必须警告您,您可能需要考虑以下问题:

    • Do you need to use ShareMM

    • 为什么要将其构建为 DLL?不能将应用程序编写为单个 EXE 吗?或者两个相互通信的EXE?