0

这是我的第一篇文章。我有一个让我头疼的大问题。我有一个应用程序使用 WinForms、TTS(文本到语音)语音和带有状态的自定义按钮。

在我的第一种形式-main-中,当我单击一个按钮时,该应用程序会在第一种形式上方打开第二种形式。行。当我通过按钮关闭第二个表单时,我告诉 TTS 说点什么,表单会自行关闭,再次查看第一个表单。行。

当我在第二种形式的按钮中单击两次时,问题就开始了:TTS 说了些什么,按钮关闭并且“第二次单击”仍在单击缓冲区(或某处)中,并且它以第一种形式进行单击(其中当我第一次按下按钮时出现 4 秒后)。我在同步模式下使用语音;如果我在异步模式下使用语音,应用程序会以一个很好的异常结束。如果我在第二种形式中单击三到四次,则其他单击仍保留在缓冲区中,并且一直在第一种形式中单击。

我尝试(1)删除 DoubleClick 事件,(2)删除与按钮关联的事件,(3)隐藏从第二个表单返回时自动单击的按钮,(4)在创建之前隐藏第一个表单2nd 完成后恢复。

建议?谢谢!

PD:对不起我的英语:S

PD2:我上传了一个非常简单的例子来说明发生了什么。

4

2 回答 2

0

使用布尔标志来跟踪表单是否处于接受点击的状态。

IE - 当你打开第二种形式时,'boolean canPlaySound = true;' 当按钮单击事件触发时,仅当 canPlaySound 为 true 时才播放声音(并在播放声音之前将其设置为 false)。

下次点击将被忽略,因为 canPlaySound = false。你不会播放声音。

于 2011-04-26T15:50:58.957 回答
0

编辑 2

查看代码后,我了解您现在遇到的问题。按钮点击堆积的原因是当您在 TTS 中调用 Speak 时,应用程序在等待功能完成时锁定。在那段时间的任何印刷机都被堆叠起来,直到应用程序再次空闲来处理它们,然后您在处理消息之前立即关闭表单,然后在第一个表单中处理这些消息。

我想出了一些可能对您有用的解决方案:

  1. 仅在 TTS 类中使用 SpeakAsync 命令并引入等待系统,您可以在其中等待语音完成,然后再执行任何操作。这将释放应用程序并且不会导致鼠标单击事件堆积。

  2. 触发 Speak 命令后,您可以访问 Windows 消息列表并清除在进程完成之前发生的所有鼠标单击事件。不幸的是,我不确定您将如何实现这一点,因为我以前没有这样做过。我认为您需要覆盖 WndProc 函数,但我又不确定。这也可能有点危险,因为您最终可能会错误地清除完全有效或重要的系统消息。抱歉,无法提供更多帮助。

  3. 以您的第二种形式实现一个后台工作程序,它将在后台线程上单独处理 Speak 命令。这将再次释放应用程序,因此鼠标单击事件不会叠加。我已经修改了您的示例项目并将其压缩以供您查看。如果您愿意,我可以进一步解释,但本质上它执行以下操作:

    • Form 2 加载并创建一个后台工作程序。
    • Worker_DoWork 和 Worker_WorkComplete 委托在后台工作人员中创建和设置。这些函数在 worker 启动时和 worker 完成后被调用。
    • 表格 2 触发后台工作人员启动。然后后台工作人员处于无限循环中等待命令处理。
    • 当按下“Hello”按钮时,这会将 SayHello 布尔值设置为 true,工作人员会发现这一点,执行适当的说话功能,然后重置布尔值以准备下一次按下。
    • 当按下“关闭”按钮时,会在后台工作人员中调用 CancelASync 请求。
    • CancelASync 中断 BackgroundWorker 的主循环(CancellationPending 变为 true)。在跳出 BackgroundWorker 的主循环之前,将发送适当的 speak 命令并将 DoWorkEventArgs 的 cancel 属性设置为 true。
    • 跳出主循环会导致 Worker_WorkComplete 被调用,然后关闭表单。

我希望你能按照这个例子(下面链接),我在这里解释得很好。我更喜欢这个解决方案,因为它非常可扩展,例如,您可以在主工作线程中添加更多条件。

就像我说的,如果您有任何问题,请提出,我会尽可能提供帮助。

希望这可以帮助。

示例链接:http ://www.mediafire.com/?2mf1yahto50ljs6

于 2011-04-26T19:27:06.333 回答