Aquí hay un enfoque que usa la página personalizada donde se crean los cuadros de edición separados. Solo necesita especificar el valor de la constante SC_EDITCOUNT
donde se define el número de cuadros de edición y el SC_CHARCOUNT
cuál es el número de caracteres que se pueden ingresar en estos cuadros de edición. Si está en el primer cuadro de edición, puede pegar el número de serie completo si está en el formato por el patrón delimitado por el carácter -
(la función TryPasteSerialNumber
aquí). Para obtener el número de serie de los cuadros de edición, es suficiente llamar al GetSerialNumber
donde también puede especificar un delimitador para el formato de salida (si es necesario).
[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;
Y aquí es cómo se ve:
Gracias TLama - las primeras pruebas son positivas. Volveré con mis comentarios finales después de las pruebas del viernes a más tardar. – RobeN
+1! y a mis favoritos – kobik
Parece que el PChar causa un problema ya que llama a un error de tipo desconocido. ¿Podrías ayudarme con eso? me han cambiado un poco la sección que se encarga de botón Siguiente estado activo/activo: 'Si la longitud (SerialEdits [I] .Texto) <5 then' que causa el botón Siguiente está inactivo hasta que todos los cuadros de edición son lleno de 5 caracteres. En su versión, un solo carácter en cada cuadro de edición hace que el siguiente botón esté activo. – RobeN