using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Core.StlMes.Client.SaleBase
{
public class TreeComboBox : ComboBox
{
#region 自定义成员变量
private TextBox m_TextBox;
private TreeView m_TreeView;
private Button m_DropdownButton;
private int m_MaxDropDownItems = 8;
//是否正在显示下拉列表
private bool b_Dropdown = false;
//使能
private bool b_Enabled = true;
//事件
public event EventHandler DropDown;
public event EventHandler DropDownClosed;
public event EventHandler EnableChanged;
public event TreeViewCancelEventHandler BeforeExpand;
public event TreeViewCancelEventHandler BeforeCollapse;
public event TreeViewEventHandler AfterExpand;
public event TreeViewEventHandler AfterCollapse;
#endregion
///
/// 构造函数
///
public TreeComboBox()
{
this.InitControls();
this.LayoutControls();
}
#region 内部辅助方法
///
/// 创建并初始化所有控件,包括添加事件处理函数
///
private void InitControls()
{
//TextBox
this.m_TextBox = new TextBox();
this.m_TextBox.KeyDown += new KeyEventHandler(m_TextBox_KeyDown);
this.m_TextBox.Parent = this;
this.m_TextBox.ReadOnly = true;
//Button
this.m_DropdownButton = new Button();
//Assembly asm = Assembly.GetExecutingAssembly();
//System.IO.Stream stream = asm.GetManifestResourceStream(asm.GetName().Name + ".BM_dropdown.bmp");
Bitmap bm = new Bitmap(this.GetType(), "BM_dropdown.bmp");
this.m_DropdownButton.Image = bm;
this.m_DropdownButton.Width = 16;
this.m_DropdownButton.Height = this.m_TextBox.Height-2;
this.m_DropdownButton.Location = new Point(this.m_TextBox.Right-18, 1);
this.m_DropdownButton.Click += new EventHandler(m_DropdownButton_Click);
this.m_DropdownButton.TextChanged += new EventHandler(m_DropdownButton_TextChanged);
this.m_DropdownButton.FlatStyle = FlatStyle.Flat;
this.m_DropdownButton.Parent = this;
this.m_DropdownButton.BringToFront();
//TreeView
this.m_TreeView = new TreeView();
this.m_TreeView.Visible = false;
this.m_TreeView.DoubleClick += new EventHandler(m_TreeView_DoubleClick);
this.m_TreeView.KeyDown += new KeyEventHandler(m_TreeView_KeyDown);
this.m_TreeView.LostFocus += new EventHandler(m_TreeView_LostFocus);
this.m_TreeView.BeforeExpand += new TreeViewCancelEventHandler(m_TreeView_BeforeExpand);
this.m_TreeView.BeforeCollapse += new TreeViewCancelEventHandler(TreeComboBox_BeforeCollapse);
this.m_TreeView.AfterExpand += new TreeViewEventHandler(m_TreeView_AfterExpand);
this.m_TreeView.AfterCollapse += new TreeViewEventHandler(TreeComboBox_AfterCollapse);
this.m_TreeView.Location = new Point(0, 0);
this.m_TreeView.Parent = null;
this.LostFocus += new EventHandler(TreeComboBox_LostFocus);
}
///
/// 布局所有控件,让TextBox尺寸适应容器尺寸
///
private void LayoutControls()
{
this.m_TextBox.Width = this.Width;
this.Height = this.m_TextBox.Height;
this.m_DropdownButton.Left = this.m_TextBox.Right - 18;
this.m_DropdownButton.Height = this.m_TextBox.Height - 2;
this.m_TreeView.Width = this.Width * 2;
this.m_TreeView.Height = (int)((this.Font.Height+3) * this.m_MaxDropDownItems);
}
///
/// 显示下拉列表
///
private void ShowDropDown()
{
if (this.Parent == null)
return;
// 智能计算显示的位置,尝试在下方显示,如果没有足够空间,则在上方显示
// 尝试在下方的位置(现在只是相对父窗口的相对位置)
Point pos = new Point(this.Left, this.Bottom-1);
// 把位置映射到顶层窗口,获取父窗口的屏幕坐标
Point parentPos = this.Parent.PointToScreen(this.Parent.Location);
// 获取顶层窗口的屏幕坐标
Point topParentPos = this.TopLevelControl.PointToScreen(this.Parent.Location);
// 把相对父窗口的位置变换为相对顶级窗口的位置,因为popup的父是顶级窗口
pos.Offset(parentPos.X - topParentPos.X, parentPos.Y - topParentPos.Y);
// 检查是否有足够空间用于在label下方显示day picker
if ((pos.Y + this.m_TreeView.Height) > this.TopLevelControl.ClientRectangle.Height)
{
// 没有足够的空间(超出了顶级窗口客户区),尝试在上方显示将Y方向,向上平移
pos.Y -= (this.Height + this.m_TreeView.Height);
if (pos.Y < 0)
{
// 如果上方仍然没有空间显示,则显示在顶级窗口的底部
pos.Y = (this.TopLevelControl.ClientRectangle.Height -this.m_TreeView.Height);
}
}
// 尝试停靠,如果右边超过顶级窗口的客户区,则将控件向左移动,并紧靠在顶级窗口右侧
if ((pos.X + this.m_TreeView.Width) > this.TopLevelControl.ClientRectangle.Width)
pos.X = (this.TopLevelControl.ClientRectangle.Width - this.m_TreeView.Width);
this.m_TreeView.Location = pos;// this.Parent.PointToScreen(pt);
this.m_TreeView.Visible = true;
this.m_TreeView.Parent = this.TopLevelControl;
this.m_TreeView.BringToFront();
this.b_Dropdown = true;
//raise event
if (this.DropDown != null)
this.DropDown(this, EventArgs.Empty);
this.m_TreeView.Focus();
}
///
/// 隐藏下拉列表
///
private void HideDropDown()
{
if (this.DropDownClosed != null)
this.DropDownClosed(this,EventArgs.Empty);
this.m_TreeView.Parent = null;
this.m_TreeView.Visible = false;
this.b_Dropdown = false;
}
#endregion
#region 事件处理 - TextBox
///
/// 在编辑框中按下按键
///
///
///
private void m_TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (this.b_Dropdown)
this.HideDropDown();
else
this.ShowDropDown();
}
else if (e.KeyCode == Keys.Down)
{
this.ShowDropDown();
this.m_TreeView.Focus();
}
}
///
/// 在编辑框改变Text
///
///
///
private void m_DropdownButton_TextChanged(object sender, EventArgs e)
{
throw new NotImplementedException();
}
#endregion
#region 事件处理 - TreeView
///
/// 在下拉列表中选择了一个节点的事件处理!
///
///
///
private void m_TreeView_KeyDown(object sender, KeyEventArgs e)
{
//如果按下回车表示要选中当前节点
if (e.KeyCode == Keys.Enter)
{
this.m_TreeView_DoubleClick(sender, EventArgs.Empty);
}
}
///
/// 失去焦点时,如果不是被下拉按钮夺取的焦点,则隐藏它!
///
///
///
void m_TreeView_LostFocus(object sender, EventArgs e)
{
if(!this.m_DropdownButton.Focused)
this.HideDropDown();
}
///
/// 在下拉列表中双击
///
///
///
private void m_TreeView_DoubleClick(object sender, EventArgs e)
{
TreeNode node = this.m_TreeView.SelectedNode;
if (node != null)
this.m_TextBox.Text = node.Text;
if (this.b_Dropdown)
{
this.HideDropDown();
}
}
void TreeComboBox_AfterCollapse(object sender, TreeViewEventArgs e)
{
if (this.AfterCollapse != null)
this.AfterCollapse(this, e);
}
void TreeComboBox_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
{
if (this.BeforeCollapse != null)
this.BeforeCollapse(this, e);
}
void m_TreeView_AfterExpand(object sender, TreeViewEventArgs e)
{
if (this.AfterExpand != null)
this.AfterExpand(this,e);
}
void m_TreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (this.BeforeExpand != null)
this.BeforeExpand(this, e);
}
#endregion
#region 事件处理 - Button
private void m_DropdownButton_Click(object sender, EventArgs e)
{
//throw new Exception("The method or operation is not implemented.");
if (this.b_Dropdown)
this.HideDropDown();
else
this.ShowDropDown();
}
#endregion
#region 事件处理 - 自身
///
/// 失去焦点
///
///
///
private void TreeComboBox_LostFocus(object sender, EventArgs e)
{
if (this.b_Dropdown)
this.HideDropDown();
}
///
/// 重设尺寸
///
///
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.LayoutControls();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.LayoutControls();
}
#endregion
#region 外部属性封装
///
/// 获取节点集合
///
public TreeNodeCollection Nodes
{
get { return this.m_TreeView.Nodes; }
}
///
/// 设置或者获取节点的图片列表
///
public ImageList ImageList
{
get
{
return this.m_TreeView.ImageList;
}
set
{
this.m_TreeView.ImageList = value;
}
}
///
/// 重写enabled属性
///
public new bool Enabled
{
get { return this.b_Enabled; }
set
{
if (this.b_Enabled != value)
{
this.b_Enabled = value;
this.m_DropdownButton.Enabled = value;
this.b_Enabled = value;
//当灰掉时,隐藏下拉列表
if (!this.b_Enabled && this.b_Dropdown)
this.HideDropDown();
if (this.EnableChanged != null)
this.EnableChanged(this, EventArgs.Empty);
}
}
}
///
/// 字体
///
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
this.m_TextBox.Font = value;
this.m_TreeView.Font = value;
//调整布局
this.LayoutControls();
}
}
///
/// 重写Text
///
public override string Text
{
get
{
return this.m_TextBox.Text;
}
set
{
if (this.Text != value)
{
this.m_TextBox.Text = value;
}
}
}
///
/// 是否显示lines
///
public bool ShowLines
{
get { return this.m_TreeView.ShowLines; }
set { this.m_TreeView.ShowLines = value; }
}
///
/// 是否显示+ -按钮
///
public bool ShowPlusMinus
{
get { return this.m_TreeView.ShowPlusMinus; }
set { this.m_TreeView.ShowPlusMinus = value; }
}
///
/// 是否显示root lines
///
public bool ShowRootLines
{
get { return this.m_TreeView.ShowRootLines; }
set { this.m_TreeView.ShowRootLines = value; }
}
///
/// 是否显示root lines
///
public bool ShowNodeToolTips
{
get { return this.m_TreeView.ShowNodeToolTips; }
set { this.m_TreeView.ShowNodeToolTips = value; }
}
///
/// 获取或者设置选中的节点!
///
public TreeNode SelectedNode
{
get
{
return this.m_TreeView.SelectedNode;
}
set
{
this.m_TreeView.SelectedNode = value;
if (value != null)
this.Text = value.Text;
}
}
public int MaxDropDownItems
{
get
{
return this.m_MaxDropDownItems;
}
set
{
if (this.m_MaxDropDownItems != value)
{
this.m_MaxDropDownItems = value;
this.m_TreeView.Height = this.m_TextBox.Height * value;
}
}
}
#endregion
}
}