缓冲按钮变化形式

发布于 2024-11-03 13:51:52 字数 612 浏览 1 评论 0原文

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

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

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

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

建议? 谢谢!

PD:我对我的英语感到抱歉:S

PD2:我上传了一个非常简单的示例会发生什么。

this is my first post. I have a huge problem which make me headaches. I have an app uses WinForms, a TTS (Text-To-Speech) voice and custom-buttons with states.

In my 1st form -main- when I click a button, the app opens a 2nd form above the 1st. Ok.
When I close the 2nd form trough a button, I tell the TTS say something and the form closed itself, viewing again the 1st form. Ok.

The problem starts when I click two times in the button on the 2nd form: the TTS says something, the button closes and the 'second click' is still in the click buffer (or somewhere) and it makes click in the 1st form (which appears 4 seconds later when I hit the button for the first time).
I am using the voice in a Sync mode; if I use the voice in an Async mode, the application ends wit h a nice exception.
If I click three or four times in the 2nd form, the other clicks still remains in buffer and clicks in the 1st form all the times.

I tried to (1) delete the DoubleClick event, (2) delete the event associated to the button and (3) hide the button which is clicked automatically when I return from the 2nd form, (4) hide the 1st form before create the 2nd and restore when it finishes.

Suggestions?
Thanks!

PD: I'm sorry by my English :S

PD2: I've uploaded a very simple example of what happens.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

呆萌少年 2024-11-10 13:51:52

编辑2

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

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

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

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

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

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

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

就像我说的,如果您有任何疑问,请询问,我会尽力提供帮助。

希望这有帮助。

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

EDIT 2

Having looked at the code I understand the issue you're having now. The reason button clicks are being stacked up is when you call Speak within TTS the application locks up while it waits for the function to finish. Any presses in that time are stacked up until the application is free again to process them, you then close the form instanly before the messages are handled and these are then dealt with in the first form.

I've come up with a few solutions which could work for you:

  1. Use only the SpeakAsync command within your TTS class and introduce a Waiting system where you wait for the speech to finish before doing anything. This will free the application and won't cause the mouse click events to stack up.

  2. After you trigger a Speak command you could access the Windows message list and clear all the mouse click events that occurred before the process finished. Unfortunately, I'm not sure how you'd implement this as I've not done this before. I think you need to overwrite the WndProc function but again I'm not sure. This might be also be a bit dangerous as you may end up clearing a perfectly valid or important system message by mistake. Sorry can't provide any more help on that one.

  3. Implement a background worker in your second form which will process the Speak commands seperately on a background thread. This again will free the application so the mouse click events won't stack up. I've modified your sample project and zipped it up for you to take a look. If you want I can explain further but essentially it does the following:

    • Form 2 loads and creates a background worker.
    • Worker_DoWork and Worker_WorkComplete delegates are created and set in the background worker. These functions are called when the worker is started and after the worker has finished.
    • Form 2 triggers the background worker to start. The background worker then sits in an infinite loop waiting for commands to process.
    • When the "Hello" button is pressed this sets a SayHello boolean to true, the worker spots this, carrys out the appropriate speak function and then resets the boolean ready for the next press.
    • When the "Close" button is pressed a CancelASync request is called in the background worker.
    • CancelASync interupts the BackgroundWorker's main loop (CancellationPending becomes true). The appropriate speak command is sent and the cancel property of the DoWorkEventArgs is set to true before breaking out of the BackgroundWorker's main loop.
    • Breaking out of the main loop causes Worker_WorkComplete to be called where the form is then closed.

I hope you can follow the example (linked below) and I've explained it well enough here. I prefer this solution as its quite extendable, you can add more conditions within the main worker thread for example.

Like I said, if you have any questions please ask and I'll try help as much as possible.

Hope this helps.

Example Link: http://www.mediafire.com/?2mf1yahto50ljs6

你的笑 2024-11-10 13:51:52

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

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

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

Use a boolean flag to track whether the form is in a state that accepts the click.

IE - when you open the 2nd form, 'boolean canPlaySound = true;' When the button click event fires, only play the sound if canPlaySound is true (and set it to false before playing the sound).

The next click will be ignored because canPlaySound = false. You won't play the sound.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文