This is how I do it.
Create a new package that will be installed in the development environment in development mode. If you have an existing package, you can continue to use it. Make sure the package requires
the designide
package. You can do this in the project manager, or simply by looking at the source of the project and adding designide
to the requires
clause.
Now add the following block to your package.
unit MakeEditable; interface procedure Register; implementation uses Windows, SysUtils, Menus, ToolsAPI; type TMakeEditable = class(TObject) private FEditorServices: IOTAEditorServices; FFileMenu: TMenuItem; FMakeEditable: TMenuItem; function MenuItemWithCaptionLike(const Menu: TMenuItem; const DesiredCaption: string): TMenuItem; procedure MakeEditableClick(Sender: TObject); public constructor Create; destructor Destroy; override; end; constructor TMakeEditable.Create; var Index: Integer; PreviousMenuItem: TMenuItem; begin inherited; FEditorServices := (BorlandIDEServices as IOTAEditorServices); FFileMenu := MenuItemWithCaptionLike((BorlandIDEServices as INTAServices40).MainMenu.Items, 'File'); if Assigned(FFileMenu) then begin PreviousMenuItem := MenuItemWithCaptionLike(FFileMenu, 'Reopen'); if Assigned(PreviousMenuItem) then begin Index := PreviousMenuItem.MenuIndex; if Index>=0 then begin FMakeEditable := TMenuItem.Create(FFileMenu); FMakeEditable.Caption := 'Ma&ke Editable'; FMakeEditable.OnClick := MakeEditableClick; FFileMenu.Insert(Index, FMakeEditable); end; end; end; end; destructor TMakeEditable.Destroy; begin FMakeEditable.Free; inherited; end; function TMakeEditable.MenuItemWithCaptionLike(const Menu: TMenuItem; const DesiredCaption: string): TMenuItem; var i: Integer; Target, Found: string; begin Target := StringReplace(LowerCase(Trim(DesiredCaption)), '&', '', [rfReplaceAll, rfIgnoreCase]); for i := 0 to Menu.Count-1 do begin Result := Menu.Items[i]; Found := StringReplace(LowerCase(Trim(Result.Caption)), '&', '', [rfReplaceAll, rfIgnoreCase]); if Pos(Target, Found)>0 then begin exit; end; end; Result := nil; end; procedure TMakeEditable.MakeEditableClick(Sender: TObject); procedure MakeFileEditable(const FileName: string); var Attributes: DWORD; begin Attributes := GetFileAttributes(PChar(FileName)); SetFileAttributes(PChar(FileName), Attributes and not FILE_ATTRIBUTE_READONLY); end; var FileName: string; FileExt: string; LinkedFileName: string; EditBuffer: IOTAEditBuffer; begin EditBuffer := FEditorServices.TopBuffer; FileName := EditBuffer.FileName; if FileExists(FileName) then begin MakeFileEditable(FileName); EditBuffer.IsReadOnly := False; FileExt := ExtractFileExt(FileName); if SameText(FileExt,'.dfm') then begin LinkedFileName := ChangeFileExt(FileName, '.pas'); end else if SameText(FileExt,'.pas') then begin LinkedFileName := ChangeFileExt(FileName, '.dfm'); end else begin LinkedFileName := ''; end; if (LinkedFileName<>'') and FileExists(LinkedFileName) then begin MakeFileEditable(LinkedFileName); end; end; end; var MakeEditableInstance: TMakeEditable; procedure Register; begin MakeEditableInstance := TMakeEditable.Create; end; initialization finalization MakeEditableInstance.Free; end.
When you compile and install this package, you will now have a new menu item in the File menu, which clears the read-only flag in the input buffer and makes the file writable.
David heffernan
source share