自定義彈出控件(上)
原理:
用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