Delphi 앱을 macOS 바람의 움직임으로 만들기

Delphi 앱



안녕, 여러분!
오늘도 Mori Mori Delphi에서 앱을 만들고 있습니까? ?
나는 딱딱하게 만들고 있습니다.

Delphi MainForm의 움직임



Delphi로 다양한 OS용 앱을 만들 수 있지만, 걱정되는 것이 macOS에서의 움직임.
Delphi 앱은 MainForm이 닫히면 앱이 종료됩니다.
개인적으로는 괜찮다고 생각하지만 macOS 사용자에게는 부자연스러운 움직임이됩니다.
즉 MainForm이 닫혀도 앱은 계속 생존해야 합니다.

macOS 바람을 만들 준비



이제 MainForm이 닫혀도 끝나지 않도록 합시다.
다만, 메뉴로부터는 종료될 필요가 있으므로 MainMenu 가 필수가 됩니다.
현재의 TMainMenu 는 제일 좌측의 메뉴가 어플리케이션 메뉴로서 표시되므로, 제일 좌측을 어플리케이션 메뉴로 한 메뉴를 만들어 둡니다.
또한 숨겨진 MainForm을 다시 표시하기 위해 창 메뉴에 표시라는 메뉴도 만들어 둡니다. 여기는 「파일」메뉴의 「신규」로서 새롭게 MainForm 를 만든다, 라고 하는 방법에서도 괜찮습니다만, 이번은 제일 간단한 방법을 나타냅니다.



또한 menuAppQuit의 바로 가기 키를 Cmd + Q로 설정하는 것이 좋습니다.



menuAppQuit 의 OnClick 이벤트 핸들러는 다음과 같이 종료할 수 있습니다.
Close가 아닌 Applicatio.Terminate를 사용하는 것이 포인트입니다.
마찬가지로 보기 메뉴에는 Show를 작성하여 MainForm을 표시합니다.
procedure TfrmMain.menuAppQuitClick(Sender: TObject); begin Application.Terminate; end; procedure TfrmMain.menuWindowShowClick(Sender: TObject); begin Show; end; 

macOS 바람으로 만드는 단계



가장 간단한 절차는 다음과 같습니다.
  • 더미 폼 만들기 (TDummyMain)
  • 독의 문맥 메뉴의 「숨기기」로 숨긴 뒤 표시시키면(자) TDummyMain 가 보여 버리므로, 그것을 막기 위해서 TDummyMain.CanShow 를 override 하고 False 를 돌려주도록 합니다.
  • MainForm.OnClose 에 이벤트 핸들러를 설정해 Action := TCloseAction.caHide; 로서 윈도우 좌상의 버튼을 눌러도 폼을 닫지 않게 합니다.
  • Application.MainForm을 TDummyMain의 인스턴스로 바꿉니다.
  • 원래 MainForm에 있던 MainMenu를 TDummyMain에 넣습니다.

  • 그리고 이런 형태가됩니다.

    이것을 모두 실장한 것이 이하입니다.
    (* * Supports macOS style behavior * * PLATFORMS * macOS * * LICENSE * Copyright (c) 2018 HOSOKAWA Jun * Released under the MIT license * http://opensource.org/licenses/mit-license.php * * HOW TO USE * uses * PK.Utils.MacDummyMain; * * type * TForm1 = class(TForm) * procedure FormCreate(Sender: TObject); * end; * * procedure TForm1.FormCreate(Sender: TObject); * begin * ReplaceMainFormForMac; * end; * * 2018/03/28 Version 1.0.0 * 2018/03/29 Version 1.0.1 * Programmed by HOSOKAWA Jun (twitter: @pik) *) unit PK.Utils.MacDummyMain; interface procedure ReplaceMainFormForMac; implementation uses System.Classes , System.UITypes , System.SysUtils , System.Rtti , FMX.Types , FMX.Forms , FMX.Menus ; type TOpenForm = class(TCommonCustomForm) end; TDummyMain = class(TCommonCustomForm) protected procedure MainFormClose(Sender: TObject; var Action: TCloseAction); function CanShow: Boolean; override; public constructor CreateNew(Owner: TComponent; Dummy: NativeInt = 0); override; end; { TDummyMain } function TDummyMain.CanShow: Boolean; begin Result := False; end; constructor TDummyMain.CreateNew(Owner: TComponent; Dummy: NativeInt = 0); begin inherited; TThread.ForceQueue( TThread.Current, procedure var MainForm: TOpenForm; Obj: TObject; MM: TMainMenu absolute Obj; RttiType: TRttiType; RttiField: TRttiField; begin // MainForm 取得  MainForm := TOpenForm(Application.MainForm); // OnClose を変更して閉じないようにする  MainForm.OnClose := MainFormClose; // 自分を MainForm に指定  Application.MainForm := Self; // Menu を載せ替える  Obj := MainForm.MainMenu; if (Obj <> nil) and (Obj is TMainMenu) then begin AddObject(MM); RttiType := SharedContext.GetType(ClassType); if RttiType <> nil then begin RttiField := RttiType.GetField('FMainMenu'); if RttiField <> nil then RttiField.SetValue(Self, MM); end; TMainMenu(MM).RecreateOsMenu; end; end ); end; procedure TDummyMain.MainFormClose(Sender: TObject; var Action: TCloseAction); begin Action := TCloseAction.caHide; end; procedure ReplaceMainFormForMac; begin {$IFDEF OSX} TDummyMain.CreateNew(Application); {$ELSE} // 他の OS では何もしない  {$ENDIF} end; end. 

    사용법



    PK.Utils.MacDummyMain을 사용하고 FormCreate에서 CreateDummyMainForm을 호출하면됩니다.
    implementation {$R *.fmx} uses PK.Utils.MacDummyMain; procedure TfrmMain.FormCreate(Sender: TObject); begin ReplaceMainFormForMac; end; 

    작동 중





    이 동작 중 스크린 샷을 보더라도 알 수는 없지만 ...
    왼쪽 상단의 빨간색 버튼을 눌러도 양식이 사라지면 응용 프로그램이 종료되지 않습니다.

    그 밖에도 폼을 내는 것과 같은 어플리케이션이라면, 「파일」메뉴등을 만들어 「신규 xxx」라고 하는 메뉴로 폼을 호출하도록(듯이) 하면, 보다 macOS풍의 동작이 될 것입니다.

    요약



    macOS의 움직임에 맞추려면 PK.Utils.MacDummyMain을 사용하면 간단합니다.
    하지만, MainForm 가 닫히는 것과 동시에 어플리케이션이 끝나도, 개인적으로는 개미입니다.

    좋은 웹페이지 즐겨찾기