假设在WinForms. NET中有下列建构。WinForms表单包含具有数个按钮的自订控件,这些按钮是传统Button类别的执行严修。其中一个按钮是表单的预设按钮。当按下ENTER时,自订控件会执行与预设按钮相关的动作。这是在重新定义的ProcessCmdKey方法中完成的:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Return)
{
buttonOK_Click(null, EventArgs.Empty);
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
默认按钮必须有额外的视觉提示,告知用户这是默认按钮(按钮内的额外边框)。如果我们在普通窗体中这样做,我们将设置它的AcceptButton属性。但是,这种方法在这里不适用。即使我们使用Control.FindForm方法或(this.Parent as Form)
之类的表达式找到父窗体,我们无法设置主机表单的AcceptButton
属性,然后以正确的方式清除它,而不会出现资源泄漏或类似的问题(在这里放置了很多技术细节,使问题变得冗长)。
解决这个任务的第一个可能的方法是重新定义或增强按钮的绘制。有没有一种相对简单的方法可以绘制一个按钮作为默认按钮,并带有相应的可视提示,而无需实现完全自定义绘制?在我的理解中,我们可以基于以下核心为默认按钮编写一个特殊的类:
internal class DefaultButton : Button
{
protected override void OnPaint(PaintEventArgs pevent)
{
Rectangle rc = new Rectangle(0, 0, this.Width, this.Height);
ButtonRenderer.DrawButton(pevent.Graphics, rc, System.Windows.Forms.VisualStyles.PushButtonState.Default);
}
}
然而,它应该考虑到焦点状态,窗体上的另一个按钮是否是焦点(在本例中,默认按钮没有用可视提示绘制),等等。我找不到一个很好的例子来作为我开发的基础。
解决我的问题的另一个可能的方法是设置protected IsDefault属性或/和在继承自Button
类的类中的重写CreateParams
方法中指定BS_DEFPUSHBUTTON标志,例如:
internal class DefaultButton : Button
{
public DefaultButton() : base()
{
IsDefault = true;
}
protected override CreateParams CreateParams
{
get
{
const int BS_DEFPUSHBUTTON = 1;
CreateParams cp = base.CreateParams;
cp.Style |= BS_DEFPUSHBUTTON;
return cp;
}
}
}
但是我无法使这个代码工作。基于这个类的按钮总是被绘制为没有默认按钮视觉提示的普通按钮。
1条答案
按热度按时间vhmi4jdf1#
我不确定原来的要求;例如,我不知道为什么UserControl本身应该设置窗体的AcceptButton,或者如果窗体上有多个此类控件的示例,预期的行为是什么。设置窗体的AcceptButton似乎不是UserControl的责任,可能有更好的解决方案,例如依赖事件和设置AcceptButton。
无论如何,下面的代码示例演示如何设置窗体的AcceptButton;也许它能帮助你找到一个解决方案。代码的亮点:
EndInit
,如下所示:((System.ComponentModel.ISupportInitialize)(userControl11)).EndInit();
,但如果您使用设计器,则设计器会处理此问题。下面是一个例子: