Inno Setup 中序列号的自定义页面

2023-11-24

如何在 Inno Setup 中使用序列号编辑框创建自定义页面? 例如。 6x5 个字符还是 7x5 个字符?

脚本应在“下一步”按钮可用之前检查是否已填写所有框。

如果可以实现复制/粘贴功能,如果剪贴板内容与序列号模式匹配,则允许填充所有编辑框,那就太好了。


这是一种使用自定义页面的方法,在该页面中创建单独的编辑框。您只需指定该值SC_EDITCOUNT定义编辑框数量的常量SC_CHARCOUNT这些编辑框中可以输入的字符数是多少。如果您位于第一个编辑框中,则可以粘贴整个序列号(如果序列号的格式是由-字符(TryPasteSerialNumber函数在这里)。要从编辑框中获取序列号,只需调用GetSerialNumber您还可以在其中指定输出格式的分隔符(如果需要)。

[Setup]
AppName=Serial number project
AppVersion=1.0
DefaultDirName={pf}\Serial number project

[code]
function SetFocus(hWnd: HWND): HWND;
  external '[email protected] stdcall';
function OpenClipboard(hWndNewOwner: HWND): BOOL;
  external '[email protected] stdcall';
function GetClipboardData(uFormat: UINT): THandle;
  external '[email protected] stdcall';
function CloseClipboard: BOOL;
  external '[email protected] stdcall';
function GlobalLock(hMem: THandle): PAnsiChar;
  external '[email protected] stdcall';
function GlobalUnlock(hMem: THandle): BOOL;
  external '[email protected] stdcall';

var
  SerialPage: TWizardPage;
  SerialEdits: array of TEdit;

const
  CF_TEXT = 1;
  VK_BACK = 8;
  SC_EDITCOUNT = 6;
  SC_CHARCOUNT = 5;
  SC_DELIMITER = '-';

function IsValidInput: Boolean;
var
  I: Integer;
begin
  Result := True;
  for I := 0 to GetArrayLength(SerialEdits) - 1 do
    if Length(SerialEdits[I].Text) < SC_CHARCOUNT then
    begin
      Result := False;
      Break;
    end;
end;

function GetClipboardText: string;
var
  Data: THandle;
begin
  Result := '';
  if OpenClipboard(0) then
  try
    Data := GetClipboardData(CF_TEXT);
    if Data <> 0 then
      Result := String(GlobalLock(Data));
  finally
    if Data <> 0 then
      GlobalUnlock(Data);
    CloseClipboard;
  end;
end;

function GetSerialNumber(ADelimiter: Char): string;
var
  I: Integer;
begin
  Result := '';
  for I := 0 to GetArrayLength(SerialEdits) - 1 do
    Result := Result + SerialEdits[I].Text + ADelimiter;
  Delete(Result, Length(Result), 1);
end;

function TrySetSerialNumber(const ASerialNumber: string; ADelimiter: Char): Boolean;
var
  I: Integer;
  J: Integer;
begin
  Result := False;

  if Length(ASerialNumber) = ((SC_EDITCOUNT * SC_CHARCOUNT) + (SC_EDITCOUNT - 1)) then
  begin
    for I := 1 to SC_EDITCOUNT - 1 do
      if ASerialNumber[(I * SC_CHARCOUNT) + I] <> ADelimiter then
        Exit;

    for I := 0 to GetArrayLength(SerialEdits) - 1 do
    begin
      J := (I * SC_CHARCOUNT) + I + 1;
      SerialEdits[I].Text := Copy(ASerialNumber, J, SC_CHARCOUNT);
    end;

    Result := True;
  end;
end;

function TryPasteSerialNumber: Boolean;
begin
  Result := TrySetSerialNumber(GetClipboardText, SC_DELIMITER);
end;

procedure OnSerialEditChange(Sender: TObject);
begin
  WizardForm.NextButton.Enabled := IsValidInput;
end;

procedure OnSerialEditKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  Edit: TEdit;
  EditIndex: Integer;
begin
  Edit := TEdit(Sender);
  EditIndex := Edit.TabOrder - SerialEdits[0].TabOrder;
  if (EditIndex = 0) and (Key = Ord('V')) and (Shift = [ssCtrl]) then
  begin
    if TryPasteSerialNumber then
      Key := 0;
  end
  else
  if (Key >= 32) and (Key <= 255) then
  begin
    if Length(Edit.Text) = SC_CHARCOUNT - 1 then
    begin
      if EditIndex < GetArrayLength(SerialEdits) - 1 then
        SetFocus(SerialEdits[EditIndex + 1].Handle)
      else
        SetFocus(WizardForm.NextButton.Handle);
    end;
  end
  else
  if Key = VK_BACK then
    if (EditIndex > 0) and (Edit.Text = '') and (Edit.SelStart = 0) then
      SetFocus(SerialEdits[EditIndex - 1].Handle);
end;

procedure CreateSerialNumberPage;
var
  I: Integer;
  Edit: TEdit;
  DescLabel: TLabel;
  EditWidth: Integer;
begin
  SerialPage := CreateCustomPage(wpWelcome, 'Serial number validation',
    'Enter the valid serial number');

  DescLabel := TLabel.Create(SerialPage);
  DescLabel.Top := 16;
  DescLabel.Left := 0;
  DescLabel.Parent := SerialPage.Surface;
  DescLabel.Caption := 'Enter valid serial number and continue the installation...';
  DescLabel.Font.Style := [fsBold];

  SetArrayLength(SerialEdits, SC_EDITCOUNT);
  EditWidth := (SerialPage.SurfaceWidth - ((SC_EDITCOUNT - 1) * 8)) div SC_EDITCOUNT;

  for I := 0 to SC_EDITCOUNT - 1 do
  begin
    Edit := TEdit.Create(SerialPage);
    Edit.Top := 40;
    Edit.Left := I * (EditWidth + 8);
    Edit.Width := EditWidth;
    Edit.CharCase := ecUpperCase;
    Edit.MaxLength := SC_CHARCOUNT;
    Edit.Parent := SerialPage.Surface;
    Edit.OnChange := @OnSerialEditChange;
    Edit.OnKeyDown := @OnSerialEditKeyDown;
    SerialEdits[I] := Edit;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = SerialPage.ID then
    WizardForm.NextButton.Enabled := IsValidInput;  
end;

procedure InitializeWizard;
begin
  CreateSerialNumberPage;
end;

它是这样的:

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Inno Setup 中序列号的自定义页面 的相关文章

  • 将用户定义的命令行参数添加到/?窗户

    使用 Inno Setup 可以添加用户定义的命令行参数 当我使用 HELP命令中未列出用户定义的参数 如何将带有描述的命令添加到 HELP window Inno Setup 6 0 支持HelpTextNote message http
  • 使用InnoIDE写入AppData目录?

    我需要写信给 C Users 用户 AppData Roaming AppName 安装过程中的文件夹 我使用 InnoIDE 程序进行设置 非常棒 然而 它似乎缺少一个 AppData 特殊文件夹来轻松访问该目录 例如 您可以使用 Des
  • 根据用户输入更改 AppID 和 AppName

    我想在同一系统上多次安装同一应用程序 例如两个用户使用两个不同的 Web 服务 每个都有自己的 在我的设置脚本中我想更改AppID and AppName基于用户的输入 例如我的默认值AppName Service App 应该改为AppN
  • 安装前检查 Java 是否存在

    我正在为 jar 应用程序创建 Inno Setup 安装程序 我现在想做的是在继续安装之前检查 java 是否存在 所以我只需要确保用户能够运行 java jar my app jar 我现在正在做的是 Code function Ini
  • 如何在 Inno Setup 中将 VCL 样式应用到基于 DLL 的表单?

    我正在将 Inno Setup Unicode 与我在 Delphi XE2 中编写的一组 DLL 一起使用 DLL 具有在安装向导 安装过程中显示的 VCL 形式 我已经尝试过实施 VCL 样式 https code google com
  • 如何从 [Code] 部分中止 /VERYSILENT 模式下的 Inno Setup 安装?

    我正在尝试从以下位置启动某个 Windows 服务 Code 部分 在AfterInstall处理程序 当它无法启动时 我想回滚安装 通常 当从 UI 运行安装程序时 WizardForm Close 做对了工作 但是当安装程序执行时 ve
  • 如何在 Inno Setup 中使用 GetVolumeInformation?

    我需要在使用 Inno Setup 创建的安装过程中获取驱动器号的卷序列号 我知道 DLL 函数可以导入到 Inno 中 但我对它还很陌生 并且在使其工作时遇到一些问题 我知道 kernel32 中的 GetVolumeInformatio
  • 安装日志文件丢失

    我制作了一个脚本 其中包括 Setup SetupLogging yes 但我找不到日志文件 好像没有被创建 它可能在哪里 可以指定我想放置它的位置吗 您可以通过设置指定日志文件的路径命令行参数 所以要记录例如到C FileName log
  • Inno Setup 选择一个目录来安装预定义集中的文件

    在这种情况下 我需要将文件安装到特定目录 但在不同的计算机上它可能位于不同的文件夹中 所以我需要检查哪个是正确的 例如 我有一个文件 需要将其安装在A文件夹或B文件夹或C文件夹 取决于计算机有A or B or C 所以我需要先检查一下计算
  • Innosetup - 在安装开始之前引用[Code]中的文件

    这是一种延续这个问题 https stackoverflow com questions 5658488 adding a help button to an innosetup wizard page 我想将一个文件包含在我的安装包中 C
  • Inno Setup,APP启动 Windows启动时

    对于 Inno 设置 我想为 Windows 启动时 MyAPP 自动启动创建一个复选框任务 我的代码如下 并且 如何编写下面的代码 DO Set AutoStart WhenWindowsStart Tasks Name StartMen
  • 从 Inno Setup 项目内部调用 MySQL

    我正在为一些使用 MySQL 的软件编写安装程序 我正在尝试运行 sql用于在安装时设置数据库的脚本 唉 我目前在执行它时遇到了很大的问题 这个问题似乎是由于这样一个事实而产生的 当你设置一条通往 sql文件内的 execute SOURC
  • Inno Setup 安装可以设置 Windows 安全组吗?

    如何在 Inno Setup 安装过程中设置 Windows 安全组 我似乎想不出正确的文本来谷歌来弄清楚 也许暗示要搜索什么就足够了 好的 我找到了一些东西 我可以使用 net localgroup Windows 命令 http tec
  • Inno Setup安装先决条件[重复]

    这个问题在这里已经有答案了 我正在通过 Inno Setup 创建一个安装程序 我看到很多关于如何检测先决条件是否存在的代码示例 但没有任何关于当我找不到先决条件时如何实际安装先决条件的代码示例 我确信它非常简单 但是我该如何安装先决条件呢
  • Inno Setup 代码部分创建隐藏文件

    我正在处理 Inno Setup 项目 该项目正在使用SaveStringToFile函数在 Code 部分 我想将此文件设置为隐藏系统文件 但我无法找到有关如何实现此操作的信息 有任何想法吗 Inno Setup Pascal Scrip
  • 在 Inno Setup 中单击“下一步”按钮时验证自定义页面上的数据

    我已经设法获得一个基本脚本来显示向导 使用CreateInputFilePage 供用户识别我用来更新 XML 文件中某些设置的文件位置 但是 我想对所选文件的输入进行一些基本检查 而不是简单地接受用户提供的任何内容 例如 如果用户在内容无
  • Inno Setup:使用缩进保存 XML 文档

    我正在尝试在 Inno Setup 中向 XML 文件添加一个新节点 节点添加正确 但下一个标记之前的换行符被删除或未添加换行符 这是我的添加节点代码 NewNode XMLDoc createElement Test XMLDoc set
  • 使用 Inno Setup 中格式化(部分粗体)的文本制作安装程序?

    有人看过 GOG com 游戏安装程序吗 如何制作像这样的欢迎文本字符串 包括单个标题中的路径和需要大小 其中部分内容加粗 以下是修改安装路径后如何更改字符串换行的示例 您可以使用TRichEditViewer http www jrsof
  • 使用 InnoSetup 创建 NLog 日志文件文件夹

    我遇到一个问题 我需要我的用户能够在没有管理员权限的情况下运行我的应用程序 但同时 我需要 NLog 能够创建它的日志文件 它需要管理员权限才能在应用程序安装在同一文件夹中 我正在尝试在应用程序目录下创建一个目录 名为Logs 并给ever
  • Inno Setup 编译失败,并显示“未指定必需参数“Root”。”即使有一个

    我是 Inno Setup 的初学者 我想创建一个安装程序 它复制两个 exe 文件并向 PATH 环境变量附加一个值 特别是我必须复制两个可执行文件 称为 pandoc exe 和 pandoc citeproc exe 这两个文件是我之

随机推荐

  • 在 PyTorch 中用向量替换对角线元素

    我一直在到处寻找与 PyTorch 等效的东西 但我找不到任何东西 L 1 np tril np random normal scale 1 size D D k 0 L 1 np diag indices from L 1 np exp
  • 如何在 Discord.js 中检查消息是否为私信?

    目前我使用的是最新版本Discord js v13 1 0 我希望能够检测某条消息是否是 DM 我尝试制作一个messageCreate事件并执行 if 语句来检查通道是否为 DM client on messageCreate messa
  • “以不同用户身份运行”Visual Studio,无法清除缓存的 TFS 凭据

    Update我设法通过向用户授予使用凭据集 2 远程连接到桌面的权限来解决此问题 从而能够从凭据管理器中删除存储的凭据 I log onto my server with one set of credentials and open Vi
  • Spring安全过滤器身份验证成功但发回403响应

    我有一个带有以下网络安全配置的 Spring Boot 应用程序 Override protected void configure HttpSecurity http throws Exception http sessionManage
  • 使用 TypeScript 和 React-Redux 时推断映射的 props

    我找到了一种在使用时获得类型安全的方法mapStateToProps from react redux as 有记录的您可以定义一个接口并参数化React Component
  • std::async 不能异步工作

    我有以下非常简单的代码 void TestSleep std cout lt lt TestSleep lt lt std endl sleep 10 std cout lt lt TestSleep Ok lt lt std endl v
  • 使用 tc 模拟特定端口上的网络延迟

    我正在尝试使用 ubuntu 上的 tc 命令模拟来自源端口 7000 的 tcp 数据包的固定时间延迟 我使用的命令是 sudo tc qdisc add dev eth1 root handle 1 prio sudo tc qdisc
  • 将 Curl 客户端 ssl 移至 Guzzle

    我正在使用 Guzzle v3 9 2 以及 php 5 3 和 php 5 5 我有以下使用 ssl 客户端证书的工作卷曲代码 url https example com cert file path to certificate pem
  • SPARQL 查询传递

    我是 SPARQL 的初学者 想知道是否有一个查询可以帮助我返回传递关系 例如下面的 n3 文件 我想要一个返回 a 与 c 相同 或类似内容的查询 谢谢 prefix
  • 我们如何或可以通过 npm 与 Meteor 使用节点模块?

    我们如何或者我们可以通过 npm 使用节点模块Meteor 或者这取决于包装API 或者有推荐的规定方法吗 流星1 3于 2016 年 3 月 28 日发布 为应用程序提供完整的 ES6 ES2015 模块支持和开箱即用的 NPM 支持 应
  • ASP.Net Core:使用共享项目在多个项目之间共享静态资源(css / js)

    从这里汲取灵感 http rion io 2017 03 22 sharing is caring using shared projects in asp net 我尝试使用共享项目在多个 ASP Net Core 项目之间共享静态资产
  • 正则表达式匹配最后一个空格字符

    我需要一些帮助 我正在寻找一个与字符串中最后一个空格字符匹配的正则表达式 我正在使用 JavaScript 和经典 ASP 我有一长串文本 我将其修剪为 100 个字符 我想删除最后一个字符 以避免由于 100 个字符的限制而修剪单词时出现
  • 强制 EditText 在按下后退时失去焦点

    当用户按下后退按钮隐藏键盘时 我试图强制 EditText 控件失去焦点 已经有很多类似的问题了 但是几个小时后 我还没有能够让它发挥作用 首先 简单介绍一下背景 我有一个带有自定义项目的 ListView 每一项都有多个 TextView
  • 在领域对象服务器上的不同用户之间共享领域?

    目前有没有办法允许多个用户访问同一个 Realm 现在我能找到的唯一方法是使用 应用程序帐户 而不是用户帐户 如建议的那样另一个问题 thanks 通常 您可以连接到虚拟路径中的 Realm 文件 它们必须始终是绝对的 因此以斜杠开头 并且
  • 角度形式数据不会附加

    我正在尝试使用 Angular 6 上传文件 但是 我似乎无法附加我的 formData 一点帮助 谢谢 home component ts export class HomeComponent implements OnInit sele
  • PHP中如何获取字符数?

    mb strlen只给出字节数 这不是我想要的 它应该适用于多字节字符 mb strlen text UTF 8
  • 您的应用程序正在使用包含 SQL 注入漏洞的内容提供商

    我有 2 个应用程序 第二个应用程序通过内容提供程序与第一个应用程序交互以获取一些凭据 今天在 Playstore 上上传我的 apk 时出现错误 SQL 注入 您的应用程序正在使用包含 SQL 注入漏洞的内容提供程序 要解决此问题 请按照
  • Java 异常错误 - Sqlite preparedStatement.setBlob

    我将图像放入数据库中 它可以是 MYSQL 数据库 服务器 或 SQLITE 数据库 路上使用的平板电脑 Java 应用程序每天与服务器同步 上传新数据并下载任何新数据 那部分运作良好 然而 要求它也能够处理图像 我们选择在数据库中使用 b
  • 自定义tinymce 4.0.5 styleselect工具栏菜单

    我正在尝试自定义默认值styleselect工具栏菜单 这样我就可以向其中添加自定义菜单元素 这个想法是将字体大小设置为styleselect子菜单 我初始化了一个TinyMCE 4 0 5通过以下方式 tinymce init langu
  • Inno Setup 中序列号的自定义页面

    如何在 Inno Setup 中使用序列号编辑框创建自定义页面 例如 6x5 个字符还是 7x5 个字符 脚本应在 下一步 按钮可用之前检查是否已填写所有框 如果可以实现复制 粘贴功能 如果剪贴板内容与序列号模式匹配 则允许填充所有编辑框