自定義彈出控件(上)
原理:
用ToolStripDropDown做為自定義控件的容器,在使用時只需調用相應事件彈出這個容器就可以了.
自定義控件必須從ToolStripControlHost類派生,並用我們需要的一個控件進行初始化(這個控件可以是標準控件,也可以是用戶控件).
製作步驟:
1.定義好一個我們需要的控件或直接選擇一個標準控件.
2.定義一個ToolStripControlHost派生類,並用先前定義的那個控件初始化.
3.使用ToolStripDropDown作為容器,將ToolStripControlHost派生類裝入,在需要的地方按設定容器的大小並彈出這個容器.
以下以製作一個DateTimeComboBox為例
1.我們打算直接彈出一個MonthCalendar控件,所以這一步就不用做.
2.定義ToolStripMonthCalendar,它繼承自ToolStripControlHost,並用一個MonthCalendar實例初始化,在這裡可以暴露MonthCalendar的一部分屬性和方法.
public
class
ToolStripMonthCalendar : ToolStripControlHost
{
// Call the base constructor passing in a MonthCalendar instance.
// 用MonthCalendar初始化
public ToolStripMonthCalendar() : base ( new MonthCalendar()) { }
public MonthCalendar MonthCalendarControl
{
get
{
return Control as MonthCalendar;
}
}
// Expose the MonthCalendar.FirstDayOfWeek as a property.
// 暴露FirstDayOfWeek屬性
public Day FirstDayOfWeek
{
get
{
return MonthCalendarControl.FirstDayOfWeek;
}
set
{
value = MonthCalendarControl.FirstDayOfWeek;
}
}
// Expose the AddBoldedDate method.
// 暴露AddBoldedDate方法
public void AddBoldedDate(DateTime dateToBold)
{
MonthCalendarControl.AddBoldedDate(dateToBold);
}
// Subscribe and unsubscribe the control events you wish to expose.
// 覆寫顯示下拉控件時調用的函數
protected override void OnSubscribeControlEvents(Control c)
{
base .OnSubscribeControlEvents(c);
// Cast the control to a MonthCalendar control.
MonthCalendar monthCalendarControl = (MonthCalendar)c;
// Add the event.
monthCalendarControl.DateChanged += new DateRangeEventHandler(OnDateChanged);
}
// 覆寫隱藏下拉控件時調用的函數
protected override void OnUnsubscribeControlEvents(Control c)
{
base .OnUnsubscribeControlEvents(c);
// Cast the control to a MonthCalendar control.
MonthCalendar monthCalendarControl = (MonthCalendar)c;
// Remove the event.
monthCalendarControl.DateChanged -= new DateRangeEventHandler(OnDateChanged);
}
// Declare the DateChanged event.
// 聲明日期變更事件
public event DateRangeEventHandler DateChanged;
// Raise the DateChanged event.
private void OnDateChanged( object sender, DateRangeEventArgs e)
{
if (DateChanged != null )
{
DateChanged( this , e);
}
}
}
{
// Call the base constructor passing in a MonthCalendar instance.
// 用MonthCalendar初始化
public ToolStripMonthCalendar() : base ( new MonthCalendar()) { }
public MonthCalendar MonthCalendarControl
{
get
{
return Control as MonthCalendar;
}
}
// Expose the MonthCalendar.FirstDayOfWeek as a property.
// 暴露FirstDayOfWeek屬性
public Day FirstDayOfWeek
{
get
{
return MonthCalendarControl.FirstDayOfWeek;
}
set
{
value = MonthCalendarControl.FirstDayOfWeek;
}
}
// Expose the AddBoldedDate method.
// 暴露AddBoldedDate方法
public void AddBoldedDate(DateTime dateToBold)
{
MonthCalendarControl.AddBoldedDate(dateToBold);
}
// Subscribe and unsubscribe the control events you wish to expose.
// 覆寫顯示下拉控件時調用的函數
protected override void OnSubscribeControlEvents(Control c)
{
base .OnSubscribeControlEvents(c);
// Cast the control to a MonthCalendar control.
MonthCalendar monthCalendarControl = (MonthCalendar)c;
// Add the event.
monthCalendarControl.DateChanged += new DateRangeEventHandler(OnDateChanged);
}
// 覆寫隱藏下拉控件時調用的函數
protected override void OnUnsubscribeControlEvents(Control c)
{
base .OnUnsubscribeControlEvents(c);
// Cast the control to a MonthCalendar control.
MonthCalendar monthCalendarControl = (MonthCalendar)c;
// Remove the event.
monthCalendarControl.DateChanged -= new DateRangeEventHandler(OnDateChanged);
}
// Declare the DateChanged event.
// 聲明日期變更事件
public event DateRangeEventHandler DateChanged;
// Raise the DateChanged event.
private void OnDateChanged( object sender, DateRangeEventArgs e)
{
if (DateChanged != null )
{
DateChanged( this , e);
}
}
}
3.在指定位置彈出容器.
public
partial
class
DateTimeComboBox : ComboBox
{
private const UInt32 WM_LBUTTONDOWN = 0x201 ;
private const UInt32 WM_LBUTTONDBLCLK = 0x203 ;
private const UInt32 WM_KEYF4 = 0x134 ;
private const UInt32 WM_CTLCOLORLISTBOX = 0x0134 ;
ToolStripMonthCalendar myTSMonthCalendar;
ToolStripDropDown tsDD;
public DateTimeComboBox()
{
InitializeComponent();
myTSMonthCalendar = new ToolStripMonthCalendar();
tsDD = new ToolStripDropDown();
// 事件調用,如果在彈出控件時並不想改變控件的屬性,這步可省略.
this .myTSMonthCalendar.MonthCalendarControl.DateChanged += new System.Windows.Forms.DateRangeEventHandler( this .myTSMonthCalendar_DateChanged);
this .myTSMonthCalendar.MonthCalendarControl.KeyDown += new System.Windows.Forms.KeyEventHandler( this .myTSMonthCalendar_KeyDown);
}
#region 事件
private void myTSMonthCalendar_DateChanged( object sender, DateRangeEventArgs e)
{
this .Text = e.End.ToShortDateString();
}
private void myTSMonthCalendar_KeyDown( object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
this .tsDD.Close();
}
#endregion
#region 方法,計算容器在彈出時的左上角坐標
// 這個函數有個點問題,它沒有考慮到彈出容器超出屏幕的情況.
private Point CalculatePoz()
{
Point point = new Point( 0 , this .Height);
if (( this .PointToScreen( new Point( 0 , 0 )).Y + this .Height + this .myTSMonthCalendar.Height) > Screen.PrimaryScreen.WorkingArea.Height)
{
point.Y = - this .myTSMonthCalendar.Height - 7 ;
}
return point;
}
#endregion
protected override void WndProc( ref Message m)
{
#region WM_KEYF4
if (m.Msg == WM_KEYF4)
{
this .Focus();
this .tsDD.Refresh();
if ( ! this .tsDD.Visible)
{
try
{
if ( this .Text != "" )
this .myTSMonthCalendar.MonthCalendarControl.SetDate(Convert.ToDateTime( this .Text));
}
catch (Exception)
{
MessageBox.Show( " Data nu este in formatul corect! " );
}
// 在彈出容器中添加項目
tsDD.Items.Add( this .myTSMonthCalendar);
// 彈出容器
tsDD.Show( this , this .CalculatePoz());
}
return ;
}
#endregion
#region WM_LBUTTONDBLCLK
if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
{
if ( ! this .tsDD.Visible)
{
try
{
if ( this .Text != "" )
this .myTSMonthCalendar.MonthCalendarControl.SetDate(Convert.ToDateTime( this .Text));
}
catch (Exception)
{
MessageBox.Show( " Data nu este in formatul corect! " );
}
// 在彈出容器中添加項目
tsDD.Items.Add( this .myTSMonthCalendar);
// 彈出容器
tsDD.Show( this , this .CalculatePoz());
}
return ;
}
#endregion
base .WndProc( ref m);
}
}
{
private const UInt32 WM_LBUTTONDOWN = 0x201 ;
private const UInt32 WM_LBUTTONDBLCLK = 0x203 ;
private const UInt32 WM_KEYF4 = 0x134 ;
private const UInt32 WM_CTLCOLORLISTBOX = 0x0134 ;
ToolStripMonthCalendar myTSMonthCalendar;
ToolStripDropDown tsDD;
public DateTimeComboBox()
{
InitializeComponent();
myTSMonthCalendar = new ToolStripMonthCalendar();
tsDD = new ToolStripDropDown();
// 事件調用,如果在彈出控件時並不想改變控件的屬性,這步可省略.
this .myTSMonthCalendar.MonthCalendarControl.DateChanged += new System.Windows.Forms.DateRangeEventHandler( this .myTSMonthCalendar_DateChanged);
this .myTSMonthCalendar.MonthCalendarControl.KeyDown += new System.Windows.Forms.KeyEventHandler( this .myTSMonthCalendar_KeyDown);
}
#region 事件
private void myTSMonthCalendar_DateChanged( object sender, DateRangeEventArgs e)
{
this .Text = e.End.ToShortDateString();
}
private void myTSMonthCalendar_KeyDown( object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
this .tsDD.Close();
}
#endregion
#region 方法,計算容器在彈出時的左上角坐標
// 這個函數有個點問題,它沒有考慮到彈出容器超出屏幕的情況.
private Point CalculatePoz()
{
Point point = new Point( 0 , this .Height);
if (( this .PointToScreen( new Point( 0 , 0 )).Y + this .Height + this .myTSMonthCalendar.Height) > Screen.PrimaryScreen.WorkingArea.Height)
{
point.Y = - this .myTSMonthCalendar.Height - 7 ;
}
return point;
}
#endregion
protected override void WndProc( ref Message m)
{
#region WM_KEYF4
if (m.Msg == WM_KEYF4)
{
this .Focus();
this .tsDD.Refresh();
if ( ! this .tsDD.Visible)
{
try
{
if ( this .Text != "" )
this .myTSMonthCalendar.MonthCalendarControl.SetDate(Convert.ToDateTime( this .Text));
}
catch (Exception)
{
MessageBox.Show( " Data nu este in formatul corect! " );
}
// 在彈出容器中添加項目
tsDD.Items.Add( this .myTSMonthCalendar);
// 彈出容器
tsDD.Show( this , this .CalculatePoz());
}
return ;
}
#endregion
#region WM_LBUTTONDBLCLK
if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
{
if ( ! this .tsDD.Visible)
{
try
{
if ( this .Text != "" )
this .myTSMonthCalendar.MonthCalendarControl.SetDate(Convert.ToDateTime( this .Text));
}
catch (Exception)
{
MessageBox.Show( " Data nu este in formatul corect! " );
}
// 在彈出容器中添加項目
tsDD.Items.Add( this .myTSMonthCalendar);
// 彈出容器
tsDD.Show( this , this .CalculatePoz());
}
return ;
}
#endregion
base .WndProc( ref m);
}
}
參考文獻:1.http://hi.baidu.com/pzy84/blog/item/22f4ef77bfd94619b151b92c.html