📄 compform.pas
字号:
nil, OPEN_EXISTING, 0, 0);
if H <> INVALID_HANDLE_VALUE then begin
Result := GetFileTime(H, nil, nil, @LastWriteTime);
CloseHandle(H);
end
else
Result := False;
end;
{ TConfigIniFile }
type
TConfigIniFile = class(TRegIniFile)
private
FMutex: THandle;
FAcquiredMutex: Boolean;
public
constructor Create;
destructor Destroy; override;
end;
constructor TConfigIniFile.Create;
begin
inherited Create('Software\Jordan Russell\Inno Setup');
{ Paranoia: Use a mutex to prevent multiple instances from reading/writing
to the registry simultaneously }
FMutex := CreateMutex(nil, False, 'Inno-Setup-IDE-Config-Mutex');
if FMutex <> 0 then
if WaitForSingleObject(FMutex, INFINITE) <> WAIT_FAILED then
FAcquiredMutex := True;
end;
destructor TConfigIniFile.Destroy;
begin
if FMutex <> 0 then begin
if FAcquiredMutex then
ReleaseMutex(FMutex);
CloseHandle(FMutex);
end;
inherited;
end;
{ TCompileForm }
procedure TCompileForm.FormCreate(Sender: TObject);
procedure ReadConfig;
var
Ini: TConfigIniFile;
WindowPlacement: TWindowPlacement;
begin
Ini := TConfigIniFile.Create;
try
{ Menu check boxes state }
ToolbarPanel.Visible := Ini.ReadBool('Options', 'ShowToolbar', True);
StatusBar.Visible := Ini.ReadBool('Options', 'ShowStatusBar', True);
FOptions.LowPriorityDuringCompile := Ini.ReadBool('Options', 'LowPriorityDuringCompile', False);
{ Configuration options }
FOptions.ShowStartupForm := Ini.ReadBool('Options', 'ShowStartupForm', True);
FOptions.UseWizard := Ini.ReadBool('Options', 'UseWizard', True);
FOptions.MakeBackups := Ini.ReadBool('Options', 'MakeBackups', False);
FOptions.FullPathInTitleBar := Ini.ReadBool('Options', 'FullPathInTitleBar', False);
FOptions.UndoAfterSave := Ini.ReadBool('Options', 'UndoAfterSave', False);
FOptions.PauseOnDebuggerExceptions := Ini.ReadBool('Options', 'PauseOnDebuggerExceptions', True);
FOptions.UseSyntaxHighlighting := Ini.ReadBool('Options', 'UseSynHigh', True);
FOptions.CursorPastEOL := Ini.ReadBool('Options', 'EditorCursorPastEOL', True);
FOptions.TabWidth := Ini.ReadInteger('Options', 'TabWidth', 2);
SyncEditorOptions;
if DefFontData.Charset = SHIFTJIS_CHARSET then begin
{ Default to MS Gothic font on a Japanese locale }
Memo.Font.Name := '俵俽 僑僔僢僋';
Memo.Font.Size := 9;
Memo.Font.Charset := SHIFTJIS_CHARSET;
end;
Memo.Font.Name := Ini.ReadString('Options', 'EditorFontName', Memo.Font.Name);
Memo.Font.Size := Ini.ReadInteger('Options', 'EditorFontSize', Memo.Font.Size);
Memo.Font.Charset := Ini.ReadInteger('Options', 'EditorFontCharset', Memo.Font.Charset);
UpdateNewButtons;
{ Window state }
WindowPlacement.length := SizeOf(WindowPlacement);
GetWindowPlacement(Handle, @WindowPlacement);
WindowPlacement.showCmd := SW_HIDE; { the form isn't Visible yet }
WindowPlacement.rcNormalPosition.Left := Ini.ReadInteger('State',
'WindowLeft', WindowPlacement.rcNormalPosition.Left);
WindowPlacement.rcNormalPosition.Top := Ini.ReadInteger('State',
'WindowTop', WindowPlacement.rcNormalPosition.Top);
WindowPlacement.rcNormalPosition.Right := Ini.ReadInteger('State',
'WindowRight', WindowPlacement.rcNormalPosition.Left + Width);
WindowPlacement.rcNormalPosition.Bottom := Ini.ReadInteger('State',
'WindowBottom', WindowPlacement.rcNormalPosition.Top + Height);
SetWindowPlacement(Handle, @WindowPlacement);
{ Note: Must set WindowState *after* calling SetWindowPlacement, since
TCustomForm.WMSize resets WindowState }
if Ini.ReadBool('State', 'WindowMaximized', False) then
WindowState := wsMaximized;
{ Note: Don't call UpdateStatusPanelHeight here since it clips to the
current form height, which hasn't been finalized yet }
StatusPanel.Height := Ini.ReadInteger('State', 'StatusPanelHeight',
StatusPanel.Height);
finally
Ini.Free;
end;
end;
var
I: Integer;
NewItem: TMenuItem;
begin
{$IFNDEF STATICCOMPILER}
FCompilerVersion := ISDllGetVersion;
{$ELSE}
FCompilerVersion := ISGetVersion;
{$ENDIF}
FInitialCurrentDir := GetCurrentDir;
FModifiedSinceLastCompile := True;
InitFormFont(Self);
FBuildImageList := ImageList_LoadBitmap(HInstance, 'BUILDIMAGES', 17, 0, clSilver);
{ For some reason, if AutoScroll=False is set on the form Delphi ignores the
'poDefault' Position setting }
AutoScroll := False;
{ Append 'Del' to the end of the Delete item. Don't actually use Del as
the shortcut key so that the Del key still works when the menu item is
disabled because there is no selection. }
EDelete.Caption := EDelete.Caption + #9 + ShortCutToText(VK_DELETE);
Memo.WindowProc := MemoWndProc;
DebugOutputList.Canvas.Font.Assign(DebugOutputList.Font);
FDebugLogListTimeWidth := DebugOutputList.Canvas.TextWidth('[00:00:00] ');
DebugOutputList.ItemHeight := DebugOutputList.Canvas.TextHeight('0');
Application.OnException := AppOnException;
Application.OnActivate := AppOnActivate;
Application.OnIdle := AppOnIdle;
FMRUList := TStringList.Create;
for I := 0 to High(FMRUMenuItems) do begin
NewItem := TMenuItem.Create(Self);
NewItem.OnClick := FMRUClick;
FMenu.Insert(FMenu.IndexOf(FMRUSep), NewItem);
FMRUMenuItems[I] := NewItem;
end;
FDebugTarget := dtSetup;
UpdateTargetMenu;
UpdateCaption;
OpenDialog.Filter := SCompilerOpenFilter;
SaveDialog.Filter := SCompilerOpenFilter;
UpdateThemeData(False, True);
if CommandLineCompile then
PostMessage(Handle, WM_StartCommandLineCompile, 0, 0)
else if CommandLineWizard then begin
{ Stop Delphi from showing the compiler form }
Application.ShowMainForm := False;
{ Show wizard form later }
PostMessage(Handle, WM_StartCommandLineWizard, 0, 0);
end else begin
ReadConfig;
if CommandLineFilename = '' then begin
if FOptions.ShowStartupForm then
PostMessage(Handle, WM_ShowStartupForm, 0, 0);
end else
OpenFile(CommandLineFilename)
end;
end;
procedure TCompileForm.FormDestroy(Sender: TObject);
procedure SaveConfig;
var
Ini: TConfigIniFile;
WindowPlacement: TWindowPlacement;
begin
Ini := TConfigIniFile.Create;
try
{ Menu check boxes state }
Ini.WriteBool('Options', 'ShowToolbar', ToolbarPanel.Visible);
Ini.WriteBool('Options', 'ShowStatusBar', StatusBar.Visible);
Ini.WriteBool('Options', 'LowPriorityDuringCompile', FOptions.LowPriorityDuringCompile);
{ Window state }
WindowPlacement.length := SizeOf(WindowPlacement);
GetWindowPlacement(Handle, @WindowPlacement);
Ini.WriteInteger('State', 'WindowLeft', WindowPlacement.rcNormalPosition.Left);
Ini.WriteInteger('State', 'WindowTop', WindowPlacement.rcNormalPosition.Top);
Ini.WriteInteger('State', 'WindowRight', WindowPlacement.rcNormalPosition.Right);
Ini.WriteInteger('State', 'WindowBottom', WindowPlacement.rcNormalPosition.Bottom);
Ini.WriteBool('State', 'WindowMaximized', WindowState = wsMaximized);
Ini.WriteInteger('State', 'StatusPanelHeight', StatusPanel.Height);
finally
Ini.Free;
end;
end;
begin
UpdateThemeData(True, False);
Application.OnActivate := nil;
Application.OnIdle := nil;
if not (CommandLineCompile or CommandLineWizard) then
SaveConfig;
DestroyDebugInfo;
FMRUList.Free;
ImageList_Destroy(FBuildImageList);
FBuildImageList := 0;
end;
class procedure TCompileForm.AppOnException(Sender: TObject; E: Exception);
begin
AppMessageBox(PChar(AddPeriod(E.Message)), SCompilerFormCaption,
MB_OK or MB_ICONSTOP);
end;
procedure TCompileForm.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if IsWindowEnabled(Application.Handle) then
CanClose := ConfirmCloseFile(True)
else
{ CloseQuery is also called by the VCL when a WM_QUERYENDSESSION message
is received. Don't display message box if a modal dialog is already
displayed. }
CanClose := False;
end;
procedure TCompileForm.FormResize(Sender: TObject);
begin
{ Make sure the status panel's height is decreased if necessary in response
to the form's height decreasing }
if StatusPanel.Visible then
UpdateStatusPanelHeight(StatusPanel.Height);
end;
procedure TCompileForm.UpdateCaption;
var
NewCaption: String;
begin
if FFilename = '' then
NewCaption := 'Untitled'
else begin
if FOptions.FullPathInTitleBar then
NewCaption := FFilename
else
NewCaption := GetDisplayFilename(FFilename);
end;
NewCaption := NewCaption + ' - ' + SCompilerFormCaption + ' ' +
FCompilerVersion.Version;
if FCompiling then
NewCaption := NewCaption + ' [Compiling]'
else if FDebugging then begin
if not FPaused then
NewCaption := NewCaption + ' [Running]'
else
NewCaption := NewCaption + ' [Paused]';
end;
Caption := NewCaption;
if not CommandLineWizard then
Application.Title := NewCaption;
end;
procedure TCompileForm.UpdateNewButtons;
begin
if FOptions.UseWizard then begin
FNew.OnClick := FNewWizardClick;
NewButton.OnClick := FNewWizardClick;
end else begin
FNew.OnClick := FNewClick;
NewButton.OnClick := FNewClick;
end;
end;
procedure TCompileForm.NewFile;
begin
FUninstExe := '';
if FDebugTarget <> dtSetup then begin
FDebugTarget := dtSetup;
UpdateTargetMenu;
end;
DestroyDebugInfo;
Memo.Text := '';
FModifiedSinceLastCompile := True;
Memo.Modified := False;
FFilename := '';
UpdateCaption;
HideError;
end;
procedure TCompileForm.NewWizardFile;
var
WizardForm: TWizardForm;
F: TFile;
begin
WizardForm := TWizardForm.Create(Application);
try
if CommandLineWizard then
WizardForm.WizardName := CommandLineWizardName;
if WizardForm.ShowModal <> mrOk then
Exit;
if CommandLineWizard then begin
F := TFile.Create(CommandLineFileName, fdCreateAlways, faWrite, fsNone);
try
F.WriteBuffer(Pointer(WizardForm.ResultScript)^, Length(WizardForm.ResultScript));
finally
F.Free;
end;
end else begin
NewFile;
Memo.Text := WizardForm.ResultScript;
Memo.Modified := (WizardForm.Result = wrComplete);
if WizardForm.Result = wrComplete then
if MsgBox('Would you like to compile the new script now?', SCompilerFormCaption, mbConfirmation, MB_YESNO) = ID_YES then
BCompileClick(Self);
end;
finally
WizardForm.Free;
end;
end;
procedure TCompileForm.OpenFile(AFilename: String);
var
Stream: TFileStream;
begin
AFilename := PathExpand(AFilename);
AddToMRUList(AFilename);
FUninstExe := '';
if FDebugTarget <> dtSetup then begin
FDebugTarget := dtSetup;
UpdateTargetMenu;
end;
DestroyDebugInfo;
Stream := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone);
try
GetFileTime(Stream.Handle, nil, nil, @FFileLastWriteTime);
Memo.Lines.LoadFromStream(Stream);
finally
Stream.Free;
end;
FModifiedSinceLastCompile := True;
Memo.Modified := False;
FFilename := AFilename;
UpdateCaption;
HideError;
end;
function TCompileForm.SaveFile(const SaveAs: Boolean): Boolean;
procedure SaveTo(const FN: String);
var
TempFN, BackupFN: String;
Buf: array[0..4095] of Char;
begin
{ Save to a temporary file; don't overwrite existing files in place. This
way, if the system crashes or the disk runs out of space during the save,
the existing file will still be intact. }
if GetTempFileName(PChar(PathExtractDir(FN)), 'iss', 0, Buf) = 0 then
raise Exception.CreateFmt('Error creating file (code %d). Could not save file',
[GetLastError]);
TempFN := Buf;
try
Memo.Lines.SaveToFile(TempFN);
{ Back up existing file if needed }
if FOptions.MakeBackups and NewFileExists(FN) then begin
BackupFN := PathChangeExt(FN, '.~is');
DeleteFile(BackupFN);
if not RenameFile(FN, BackupFN) then
raise Exception.Create('Error creating backup file. Could not save file');
end;
{ Delete existing file }
if not DeleteFile(FN) and (GetLastError <> ERROR_FILE_NOT_FOUND) then
raise Exception.CreateFmt('Error removing existing file (code %d). Could not save file',
[GetLastError]);
except
DeleteFile(TempFN);
raise;
end;
{ Rename temporary file.
Note: This is outside the try..except because we already deleted the
existing file, and don't want the temp file also deleted in the unlikely
event that the rename fails. }
if not RenameFile(TempFN, FN) then
raise Exception.CreateFmt('Error renaming temporary file (code %d). Could not save file',
[GetLastError]);
GetLastWriteTimeOfFile(FN, FFileLastWriteTime);
end;
var
FN: String;
begin
Result := False;
if SaveAs or (FFilename = '') then begin
SaveDialog.Filename := FFilename;
if not SaveDialog.Execute then Exit;
FN := PathExpand(SaveDialog.Filename);
SaveTo(FN);
FFilename := FN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -