gpt4 book ai didi

c# - 将 WinForms 表单嵌入到 Inno Setup 向导中

转载 作者:太空狗 更新时间:2023-10-30 01:02:15 25 4
gpt4 key购买 nike

我需要将一个 WinForms 表单(使用 BorderStyle = None)嵌入到 Inno 设置向导中,但遇到了问题。

这是一个 Inno Setup 脚本:

procedure EmbedConfiguratorForm(parentWnd: HWND);
external 'EmbedConfiguratorForm@files:configurator.dll stdcall';

procedure InitializeWizard();
var
cfgPageHandle: HWND;
begin
cfgPageHandle := CreateCustomPage(wpSelectDir,
'Configuration',
ExpandConstant(description)).Surface.Handle;
EmbedConfiguratorForm(cfgPageHandle);
end;

这是一段C#代码:

class WizardWindow : IWin32Window
{
public WizardWindow(IntPtr handle)
{
Handle = handle;
}

public WizardWindow(int handle) : this(new IntPtr(handle))
{
}

public IntPtr Handle { get; private set; }
}

public static class MainClass
{
[DllExport("EmbedConfiguratorForm", CallingConvention.StdCall)]
public static void EmbedConfiguratorForm(int parentWnd)
{
// System.Diagnostics.Debugger.Launch();
ConfiguratorForm form = new ConfiguratorForm();
form.Show(new WizardWindow(parentWnd));
}
}

它有效但不如预期。安装程序加载后,它会自动从 configurator.dll 调用 EmbedConfiguratorForm 并且表单显示但不进入安装向导页面。它显示在后面(见屏幕截图)。那我做错了什么?

enter image description here

最佳答案

已解决。

解决方案是从 DLL 返回新窗口(窗体)的句柄,并使用 user32.SetParent WinAPI 函数强制将窗体嵌入到向导中。这里有一段代码。

C#:

namespace configurator
{
class WizardWindow : IWin32Window
{
public WizardWindow(IntPtr handle)
{
Handle = handle;
}

public WizardWindow(int handle) : this(new IntPtr(handle))
{
}

public IntPtr Handle { get; private set; }
}

public static class MainClass
{
private static ConfiguratorForm _configuratorForm;

[DllExport("EmbedConfiguratorForm", CallingConvention.StdCall)]
public static IntPtr EmbedConfiguratorForm(int parentWnd)
{
_configuratorForm = new ConfiguratorForm();
_configuratorForm.Show(new WizardWindow(parentWnd));
return _configuratorForm.Handle;

}

[DllExport("CloseConfiguratorForm", CallingConvention.StdCall)]
public static void CloseConfiguratorForm()
{
if (_configuratorForm != null)
{
_configuratorForm.Close();
_configuratorForm.Dispose();
_configuratorForm = null;
}
}
}
}

Inno 安装脚本:

[Code]
const
description = 'my page description';

var
configFile: string;
configuratorPage: TWizardPage;

function EmbedConfiguratorForm(parentWnd: HWND): HWND;
external 'EmbedConfiguratorForm@files:configurator.dll stdcall';

procedure CloseConfiguratorForm();
external 'CloseConfiguratorForm@files:configurator.dll stdcall';

function SetParent(hWndChild, hWndNewParent: HWND): HWND;
external 'SetParent@user32.dll stdcall';

procedure InitializeWizard();
begin
configuratorPage := CreateCustomPage(wpSelectDir,
'Title', 'Description');
end;

procedure ShowConfigurationStep();
var
cfgPageHandle: HWND;
cfgWinHandle: HWND;
begin
cfgPageHandle := configuratorPage.Surface.Handle;
cfgWinHandle := EmbedConfiguratorForm(cfgPageHandle);
SetParent(cfgWinHandle, cfgPageHandle);
end;

procedure CurPageChanged(CurPageId: Integer);
begin
if (CurPageId = configuratorPage.ID) then
begin
ShowConfigurationStep();
end else
begin
CloseConfiguratorForm(); // here we can make some optimization like checking previos page
end;
end;

procedure DeinitializeSetup();
begin
CloseConfiguratorForm();
end;

关于 C# DLL 的注意事项:
它使用 UnmanagedExports NuGet 数据包(包含 DLLExportAttribute)。

关于 Inno Setup 脚本的注意事项:
InitializeWizard 函数中,我们只需要创建新页面,但我们需要将 DLL 调用实现到 CurPageChanged 中,以确保我们的页面现在打开。


经过一些研究工作后,我创建了一个小示例项目来解释 .Net 和 InnoSetup 的双向集成

https://github.com/sharpcoder7/innoGlue.net

关于c# - 将 WinForms 表单嵌入到 Inno Setup 向导中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34581407/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com