【问题标题】:Buffer button changing forms缓冲区按钮更改表单
【发布时间】:2011-04-26 15:46:30
【问题描述】:

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

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

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

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

建议? 谢谢!

PD:我的英语很抱歉:S

PD2:I've uploaded a very simple example 会发生什么。

【问题讨论】:

    标签: c# click mouse buffer wfp


    【解决方案1】:

    编辑 2

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

    我想出了一些适合您的解决方案:

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

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

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

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

    我希望您可以按照示例(链接如下)进行操作,并且我在此处已对其进行了充分的解释。我更喜欢这个解决方案,因为它的可扩展性很强,例如,您可以在主工作线程中添加更多条件。

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

    希望这会有所帮助。

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

    【讨论】:

    • 没用。不仅是那个按钮,点击仍然在缓冲区中,并且可以点击第二种形式的任何地方。如果隐藏第一种形式不起作用,我不知道该怎么办。
    • 哦,我很抱歉我误读了这个问题。我现在将编辑我的答案,看看新的解决方案是否对您有帮助。
    • 我已经进行了编辑@zaba 我希望我现在已经了解了您的问题并为您提供了可行的解决方案。如果您遇到任何困难,请告诉我
    • 我无法访问事件中的 e.Handled 方法。写对了吗?
    • 添加了一个带有迷你示例项目的链接。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多