1

確かに、これはやや難解な質問ですが、実際には、私が作業中の DM スクリプト モジュールに影響を与えます。カスタム モーダル ダイアログを使用して、延期されたメイン スレッド タスクによって検出されたエラー状態をユーザーに警告しようとしています。ほとんどの場合、これで問題なく動作しますが、エラー メッセージが表示されたときに DM アプリ ウィンドウが最小化されていた場合、DM がフォアグラウンド アプリとして復元されたときに奇妙な状態になってしまいます。モーダル ダイアログは非表示ですが、「Enter」キーまたは「Esc」キーストロークで閉じるまで、DM 内でのユーザー アクションを禁止します。

以下のサンプル コードは、問題を示しており、GMS 1 で機能するソリューションについて言及しています。

GMS 2 以降で機能する類似またはより優れた回避策はありますか?

class DeferredAlertTask
{
    Number deferredTaskID;

    DeferredAlertTask(Object self)
    {
        Number taskDelay_sec = 5;
        String message = "Click OK and then minimize the DM app window.\n";
        message += "After 5 seconds, select DM on the task bar to restore it.\n";
        message += "Dialog will be invisible, must hit 'enter' or 'esc' to go on.";
        OKDialog(message);

        deferredTaskID = AddMainThreadSingleTask(self, "Task", taskDelay_sec);
    }

    void Task(Object self)
    {
        String banner = "Error dialog";
        String message = "Error message details.";

        // Create the dialog box descriptor TagGroup
        TagGroup dialogItemsSpec;
        TagGroup dialogSpec = DLGCreateDialog(banner, dialogItemsSpec);

        // Create and add the content box and text field to the layout
        TagGroup contentBoxItemsSpec;
        TagGroup contentBoxSpec = DLGCreateBox(contentBoxItemsSpec);
        TagGroup contentLabelSpec = DLGCreateLabel(message);
        contentBoxItemsSpec.DLGAddElement(contentLabelSpec);
        dialogItemsSpec.DLGAddElement(contentBoxSpec);

        // If the DM app window has been minimized, 
        // this modal dialog will be invisible,
        // but it will still inhibit further user action
        // within DM as it awaits 'esc' or 'enter'.

        // The following is a remedy that works in GMS1, but not in GMS2
        // GetApplicationWindow().WindowSelect();

        Object dialog = Alloc(UIFrame).Init(dialogSpec);
        String result = (dialog.Pose()) ? "OK" : "Cancel";
        OKDialog(result);
    }
}

void main()
{
    Alloc(DeferredAlertTask);
}

main();
4

1 に答える 1

1

LaunchExternalProcess() 関数と外部プログラムに基づくソリューションの提案により、回答への道が提供されました。AutoHotKeyと呼ばれる無料のオープン ソース Windows マクロ作成パッケージを使用して、RestoreDM.exe という名前の非常にコンパクトな実行可能ファイルを作成することができました。この実行可能ファイルを DM スクリプトから簡単にアクセスできるフォルダーに配置することで、LaunchExternalProcessAsync() を介して起動し、カスタム ダイアログを送信する前に DM アプリ ウィンドウが復元されるようにすることができます。以下は、このソリューションを示し、AutoHotKey スクリプトに関する詳細を提供する元のテスト スクリプトの修正版です。

class DeferredAlertTask
{
    Number deferredTaskID;

    DeferredAlertTask(Object self)
    {
        Number taskDelay_sec = 5;
        String message = "Click OK and then minimize the DM app window.\n";
        message += "After 5 seconds, select DM on the task bar to restore it.\n";
        message += "Dialog will be invisible, must hit 'enter' or 'esc' to go on.";
        OKDialog(message);

        deferredTaskID = AddMainThreadSingleTask(self, "Task", taskDelay_sec);
    }

    void Task(Object self)
    {
        String banner = "Error dialog";
        String message = "Error message details.";

        // Create the dialog box descriptor TagGroup
        TagGroup dialogItemsSpec;
        TagGroup dialogSpec = DLGCreateDialog(banner, dialogItemsSpec);

        // Create and add the content box and text field to the layout
        TagGroup contentBoxItemsSpec;
        TagGroup contentBoxSpec = DLGCreateBox(contentBoxItemsSpec);
        TagGroup contentLabelSpec = DLGCreateLabel(message);
        contentBoxItemsSpec.DLGAddElement(contentLabelSpec);
        dialogItemsSpec.DLGAddElement(contentBoxSpec);

        // If the DM app window has been minimized, 
        // this modal dialog will be invisible,
        // but it will still inhibit further user action
        // within DM as it awaits 'esc' or 'enter'.

        // The following is a remedy that works in GMS1, but not in GMS2
        // GetApplicationWindow().WindowSelect();

        // For GMS2, we can use an executable that restores the DM app window.
        // The lines below launch RestoreDM.exe, placed in C:\ProgramData\Gatan,
        // where RestoreDM is an executable of the following AutoHotKey script:
        // IfWinNotActive, Digital Micrograph
        //      WinRestore, Digital Micrograph
        String commandDir = GetApplicationDirectory(3, 0);
        String restoreCommand = commandDir.PathConcatenate("RestoreDM");
        LaunchExternalProcessAsync(restoreCommand);
        Sleep(0.1);

        Object dialog = Alloc(UIFrame).Init(dialogSpec);
        String result = (dialog.Pose()) ? "OK" : "Cancel";
        OKDialog(result);
    }
}

void main()
{
    Alloc(DeferredAlertTask);
}

main();

非同期バリアント LaunchExternalProcessAsync() を使用する必要があります。これは、遅延アラート タスクがメイン スレッドで呼び出され、RestoreDM プログラムによってプロンプトが表示されたときに DM がウィンドウを復元するのをブロックするためです (DM がハングする原因となります)。また、カスタム ダイアログが表示される前に DM アプリ ウィンドウが確実に復元されるように、外部プログラムを呼び出した後、短いスリープ状態が必要になることにも注意してください。

于 2016-10-10T22:55:07.577 に答える