C#、容器火灾事件
我有一个继承自 Button 的 MyButton 类。在这个类中,我放置了几个其他控件(标签、进度栏)。这样做的问题是 Button 上的控件无法触发 Button.Click 或 Button.MouseHover 事件。如何实现按钮上的控件仅显示但“事件透明”:在标签和进度栏上单击/悬停与直接在按钮上单击/悬停(包括发件人和所有内容)相同。类似“从父级继承事件”之类的东西。
class MyButton : Button
{
Label foo = new Label();
ProgressBar bar = new ProgessBar();
}
I have a MyButton class that inherits from Button. On this class I have placed several other controls (Labels, Progessbar). The problem with this is that the controls on the Button make it impossible to fire the Button.Click or Button.MouseHover event. How can I achieve it that the controls on the Button are only displayed but are "event transparent": A click/hover on the label and progessbar is the same as if I clicked/hover directly on the Button (including sender and everything). Something like "inheriting the events from the parent".
class MyButton : Button
{
Label foo = new Label();
ProgressBar bar = new ProgessBar();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该从 UserControl 派生,然后将按钮作为子控件,并在单击事件上冒泡按钮子控件。
这个链接可能超出了您的需要,但它是一个很好的起点。
更新
正如所指出的,您可能没有使用 ASP.NET。所以这里是另一篇文章它讨论了不同的自定义用户控件,特别是您所追求的是
复合控件
。这是针对 Windows 窗体的。You should derive from UserControl then have the button as a child control, and bubble up the button child's on click event.
This link is probably more than what you need, but it's a good starting point.
UPDATE
As pointed out, you may not be using ASP.NET. So here is another post that talks about different custom user controls, specifically what you're after is a
Composite Control
. This is for Windows Forms.为标签和PB编写Click事件处理程序,让它们调用PerformClick()。
使控件对鼠标透明是可能的,但做起来很难看。您必须重写 WndProc() 才能捕获 WM_NCHITTEST 并返回 HTTRANSPARENT。全面更好的解决方案是不使用控件。标签只是按钮的 Paint 事件中的 TextRenderer.DrawText() 。 ProgressBar 也不难,e.Graphics.FillRectangle()。
Write Click event handlers for the label and PB, have them call PerformClick().
Making controls transparent to the mouse is possible but is ugly to do. You'd have to override WndProc() to catch WM_NCHITTEST and return HTTRANSPARENT. The all-around better solution is to not use controls. A Label is just TextRenderer.DrawText() in the button's Paint event. ProgressBar isn't hard either, e.Graphics.FillRectangle().
让子控件成为按钮前面的真实控件(无论是在从
Button
继承的类中还是从UserControl
继承)可能会使按钮特定的事件难以正常工作,正如您所发现的。 (编辑:虽然很难,但并非不可能 - 请参阅 Hans Passant 的答案)作为一种解决方法,您可以将它们自定义绘制到按钮表面,而不是使用子控件,因为您不需要控件的大部分功能(事件、聚焦等),只需要它们的显示。
您可以在类的
OnPaint
方法中进行额外的绘制。类似于:要更新显示,您需要使用
Invalidate()
触发按钮的重新绘制。有关更完整的示例,请参阅在 CodeProject 上使用 C# 的自定义位图按钮 。
Having the child controls be real controls in front of the button (either in a class inheriting from
Button
or fromUserControl
) may make it hard to get button-specific events working properly, as you have found. (Edit: Although it's hard, it's not impossible -- see Hans Passant's answer)As a workaround, instead of using child controls, you could custom-paint them onto the button surface, since you don't need most of the functionality of the controls (events, focusing, etc.), just their display.
You can do the additional painting in the
OnPaint
method of your class. Something like:To update the display, you would need to trigger a repaint of the Button using
Invalidate()
.Take a look at Custom Bitmap Button Using C# on CodeProject for a more complete example.
这个答案刚才就在这里,但被删除了:
Can you acquire from
UserControl
相反?这将允许您在控制表面上放置其他控件,包括您的按钮并订阅它们的事件。This answer was here a moment ago, but got deleted:
Can you inherit from
UserControl
instead? This will allow you to place other controls on the control surface, including your button and subscribe to their events.如果您使用的是 WPF,我想您正在寻找的是一种称为冒泡事件的东西。这是 WPF 中的一项功能,通过该功能,事件从控件冒泡到其父级(在您的情况下,事件将从您的 ProgressBar 和 Label 到您的按钮)。我找到了这篇关于此事的文章,我认为这会对您有所帮助。
希望这有帮助:)
If you're using WPF, I guess what you're looking for would be something called Bubbled Events. It's a feature in WPF by which events are bubbled from a control to its parent (in your case, it would be from your ProgressBar and Label to your button). I found this article on the matter which I think would be of help to you.
Hope this helps :)