当然,这是一个相当不可思议的问题,但实际上确实影响了我正在开发的DM脚本模块。我正在尝试使用自定义模式对话框来提醒用户注意由延迟的主线程任务检测到的错误情况。在大多数情况下,这工作得很好,但是如果在发布错误消息时恰好将DM应用程序窗口最小化,则当将DM应用程序窗口还原为前台应用程序时,它会以一种奇怪的状态结束。模态对话框是不可见的,但是它仍然禁止DM中的用户操作,直到通过“ enter”或“ esc”键将其关闭为止。
下面的示例代码演示了该问题,并提到了在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();
建议以LaunchExternalProcess()函数和外部程序为基础的解决方案提供了答案的途径。通过使用免费的开源Windows宏创建程序包AutoHotKey,我已经能够创建一个非常紧凑的名为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应用程序窗口。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句