对于.Net的界面编程,特别是对原有的系统控件的重绘,经常会遇到OnPaint不能使用的问题,而事实上,OnPaint对于很多的系统控件都不能使用。在OnPaint不能使用的时候,就要使用WndProc方法了。这是一个捕捉Windows消息的方法,针对不同的Windows消息做不同的反应,如重绘消息时,重新画控件,就可以修改控件的外观。
效果图
下面的图形,就是当ComboBox是Focused时,就会显示边框。
代码
下面是一个简单的例子,是对ComboBox的重绘,在控件Focused的时候,为控件增加一条边框,注意到WM_PAINT消息就是重绘的,它只是一个Windows消息,也就是简单的一个数据,在这时,它表示15,下面,override WndProc时,增加一个边框,this.DesignMode意思是,当前的是设计模式,如果是设计模式,就不画了。m.Msg ==WM_PAINT,就是指捕捉重绘消息,并做出反应,Graphics.FromHwnd(Handle)意思是获取Graphics的实例,利用ComboBox的句柄,提取出实例。
public
partial
class
ComboBox : System.Windows.Forms.ComboBox
... {
Color _defaultColor = SystemColors.Control;
Color _focusColor = Color.Blue;
const int WM_PAINT = 0x000F;
public ComboBox()
...{
InitializeComponent();
}
/**////
/// 重写WndProc方法
///
///
protected override void WndProc(ref Message m)
...{
base.WndProc(ref m);
if (this.DesignMode) return;
if(m.Msg ==WM_PAINT)
...{
Graphics g = Graphics.FromHwnd(Handle);
DrawBoxBorder(g);
g.Dispose();
}
}
/**////
/// 画ComboBox的边框
///
///
private void DrawBoxBorder(Graphics g)
...{
Rectangle rect = this.ClientRectangle;
if (this.Focused == false || this.Enabled == false)
ControlPaint.DrawBorder(g, rect, _defaultColor, ButtonBorderStyle.Solid);
else
ControlPaint.DrawBorder(g, rect, _focusColor, ButtonBorderStyle.Solid);
}
}
... {
Color _defaultColor = SystemColors.Control;
Color _focusColor = Color.Blue;
const int WM_PAINT = 0x000F;
public ComboBox()
...{
InitializeComponent();
}
/**////
/// 重写WndProc方法
///
///
protected override void WndProc(ref Message m)
...{
base.WndProc(ref m);
if (this.DesignMode) return;
if(m.Msg ==WM_PAINT)
...{
Graphics g = Graphics.FromHwnd(Handle);
DrawBoxBorder(g);
g.Dispose();
}
}
/**////
/// 画ComboBox的边框
///
///
private void DrawBoxBorder(Graphics g)
...{
Rectangle rect = this.ClientRectangle;
if (this.Focused == false || this.Enabled == false)
ControlPaint.DrawBorder(g, rect, _defaultColor, ButtonBorderStyle.Solid);
else
ControlPaint.DrawBorder(g, rect, _focusColor, ButtonBorderStyle.Solid);
}
}
ControlPaint.DrawBorder与g.DrawRectangle
是调用系统的方法来画一个边框,注意的是,使用这个方法与g.DrawRectangle是不同的,在使用Rectangle时,大小和位置是不同。这需要自己来体会。同时,ControlPaint.DrawBorder比后者在绘画时更有效。