Dưới đây là một cách tiếp cận sử dụng trang tùy chỉnh nơi tạo các hộp chỉnh sửa riêng biệt. Bạn chỉ cần chỉ định giá trị cho hằng số SC_EDITCOUNT
trong đó số hộp chỉnh sửa được xác định và số SC_CHARCOUNT
số ký tự có thể được nhập vào các hộp chỉnh sửa này là gì. Nếu bạn đang ở trong hộp chỉnh sửa đầu tiên, bạn có thể dán toàn bộ số sêri nếu nó ở định dạng theo mẫu được giới hạn bởi -
char (hàm TryPasteSerialNumber
tại đây). Để lấy số sê-ri từ các hộp chỉnh sửa, nó đủ để gọi GetSerialNumber
nơi bạn cũng có thể chỉ định một dấu tách cho định dạng đầu ra (nếu cần).
[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;
Và đây là cách nó trông giống như:
Cảm ơn bạn TLama - kiểm tra đầu tiên là tích cực. Tôi sẽ lấy lại ý kiến cuối cùng của tôi sau khi kiểm tra vào thứ Sáu chậm nhất. – RobeN
+1! và yêu thích của tôi. – kobik
Có vẻ như PChar gây ra sự cố vì nó gọi lỗi của Loại Không xác định. Bạn có thể giúp đỡ về điều đó? Tôi đã thay đổi một phần chút đó là trách nhiệm Nút Tiếp kích hoạt tiểu bang/Unactive: 'nếu Chiều dài (SerialEdits [I] .text) <5 then' Đó gây Nút Tiếp theo là Inactive đến khi tất cả Sửa Boxes là chứa đầy 5 ký tự. Trong phiên bản single char của bạn trong mỗi Edit Box làm cho nút Next hoạt động. – RobeN