2012-04-30 5 views
17

¿Cómo crear una página personalizada en la configuración Inno con cuadros de edición para el número de serie? P. ej. 6x5chars o 7x5chars?Página personalizada para el número de serie en la configuración Inno

El script debe verificar si todas las casillas están llenas antes de que el botón Siguiente esté disponible.

También sería bueno si hubiera una función de Copiar/Pegar implementada que permitiría llenar todas las Cajas de Edición si el contenido del Portapapeles coincide con el patrón de número de serie.

Respuesta

33

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:

enter image description here

+2

Gracias TLama - las primeras pruebas son positivas. Volveré con mis comentarios finales después de las pruebas del viernes a más tardar. – RobeN

+2

+1! y a mis favoritos – kobik

+0

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

7

Puede hacer que Inno solicite al usuario una clave de serie agregando una función de evento CheckSerial().

Si desea tener más control sobre la página, puede usar una de las páginas de stock (CreateInput...Page) o una página personalizada en el asistente de configuración usando CreateCustomPage() y agregar controles según lo requiera.

Vea el ejemplo codedlg.iss incluido con la configuración de Inno.

+0

¡Y +1 aquí también! :) – kobik

2

La forma más sencilla de añadir una caja de llaves de serie, por debajo de los campos de texto nombre y organización, es añadir algo como lo siguiente a su archivo iss.

[Code] 

    function CheckSerial(Serial: String): Boolean; 
    begin 
    // serial format is XXXX-XXXX-XXXX-XXXX 
    Serial := Trim(Serial); 
    if Length(Serial) = 19 then 
    result := true; 
end; 

Esto puede ser ventajoso combinar con

[Setup] 
DefaultUserInfoSerial={param:Serial} 

que llenará en la serie si se ha introducido previamente para la instalación.

+0

... ['como Deanna ya dijo'] (http://stackoverflow.com/a/10385420/960757) ... – TLama

+0

¿Dónde agregar la validación de la clave de serie? –

+0

http://stackoverflow.com/questions/11246105/how-can-i-set-the-serial-for-this-serial-form-inno-setup –

Cuestiones relacionadas