【发布时间】:2018-02-28 12:56:28
【问题描述】:
我想以某种方式使 Windows 窗体控件变得不负责任——比如将 Control.Enabled 设置为 False,但没有它的视觉效果(我将有一些自定义的“控件正忙”指示器,所以它不会不清楚最终用户为什么控件没有响应)。
原因是:我正在为 windows 窗体编写一个繁忙的指示器控件,并希望它尽可能通用。
目的是能够像下面这样使用它。
Dim busy_control As Control = ...
ShowBusyIndicator(busy_control)
BeginDoWork() 'starts a worker thread
'in some OnCompleted-Event:
HideBusyIndicator(busy_control)
我当前的问题是,我想确保busy_control 根本不会对任何用户输入做出反应。
在当前版本中,我通过处理 GotFocus 事件确保控件失去焦点并且永远无法再次获得焦点。由于覆盖控件的Parent是busy_control,所以我还将OnMouseWheel事件设置为handled(否则busy_control可以滚动)。
我想还有更多这样的事件。这就是为什么我想“禁用”控件而不实际将启用设置为 false。
有什么办法吗?
【问题讨论】:
-
如果你想保证在你的运行任务完成之前它不会接受输入,不要多线程它。只需取消注册您的
OnClick事件以确保没有任何事情发生,然后在 UI 线程上运行您的方法,然后重新注册事件。但是,这很可能会让您的用户感到困惑。用户期望“禁用”行为。 -
如果我想显示动画 gif(或让应用程序负责),我无法在 UI 线程上完成工作。如果没有一些反射黑客,我也无法禁用所有事件 - 这感觉很脏。
-
正确。如果你想保持应用程序响应,你不能在 UI 线程上工作。如果您只是希望这个表单对象本身表现得好像它被禁用了,您不需要反射来删除它的处理程序,但是有一个更好的方法。等一下……
-
在禁用它之前使用 Graphics.DrawToBitmap() 对其进行截图。在您放在控件前面的 PictureBox 中显示它。假装控件仍然可用是非常糟糕的 UI。
-
@HansPassant 的“忙碌指示器”通过绘制一个带有旋转圆圈的半透明覆盖层,很明显控件不可用