C# ToolStripMenuItem dropdownitems项太多如何平铺展开 10
软糖来回答把。
自己平铺多个List控件,当点击dropdown时,显示这些控件,并把要显示的项,根据编号,分配到这些控件中。
自己写控件。
上图是软糖写的GDI绘制的控件,给出部分源码以供参考
using System;
using System.Collections.Generic;
using System.Drawing;
using 引擎.绘图.GDI;
using 引擎.输入;
namespace 引擎.界面 {
/// <summary>
/// 可以输入文本,点击下拉箭头选择列表项目,在右边还可以附带几个按钮
/// </summary>
public class 下拉框 : 文本框, I组合控件 {
/// <summary>内置的列表控件</summary>
public 列表框 列表;
/// <summary>附加按钮的文字</summary>
public List<string> 按钮文字 = new List<string>();
/// <summary>按钮的宽度</summary>
public int 按钮宽度 = 16;
/// <summary>箭头图案的缩小比例。默认为0.25表示75%。</summary>
public double 图案缩小比例 = 0.25;
/// <summary>展开状态在-1000 到 1000之间</summary>
public int 展开状态 = 0;
/// <summary>最大的显示行数</summary>
public int 显示行数 = 8;
/// <summary>显示名称的那列的宽度</summary>
public int 名称列宽 = 32;
/// <summary>TODO: 双击可以输入文本</summary>
public bool 禁用输入 = false;
/// <summary>展开所需帧数:1000 / 展开速度</summary>
public int 展开速度 = 100;
/// <summary>当鼠标移出列表时关闭列表</summary>
public bool 鼠标移出后关闭列表 = true;
/// <summary>箭头的元素样式</summary>
public 箭头样式 箭头样式;
/// <summary>默认网格线的边框样式</summary>
public static 边框 默认网格线 = new 边框(90, Color.FromArgb(174, 174, 174), 1.0f);
public 下拉框() : base(false) {
初始化参数();
初始化事件();
宽 = 124;
高 = 24;
背景色 = Color.FromArgb(255, Color.LightSlateGray);// Color.FromArgb(224, 224, 224);
列表 = new 列表框();
列表.列数 = 1;
列表.格高 = 24;
列表.背景色 = Color.FromArgb(192, Color.LightSlateGray);
列表.网格线 = 默认网格线;
列表.可见 = false;
列表.自动卷动.速度 = 12;
列表.自动卷动.允许 = 2;
列表.自动卷动.判定边距 = 40;
列表.格式 = 文字靠中;
//列表选择项目时
列表.选择项目时 += (上次选中号) => {
if (展开状态 >= 1000) {
//文字 变为 值 (为null时) 变为 名称 (也为null时) 变为空字符串""
if (列表.项.非空(列表.选中号)) {
string str = 列表.项[列表.选中号].值;
if (str == null) {
str = 列表.项[列表.选中号].名称;
if (str == null) { 文字 = ""; } else { 文字 = str; }
}
else { 文字 = str; }
}
已选中 = false;
隐藏TextBox(false);
关闭列表();
}
};
//初始化热点区域
热区 = new Region(矩形);
同步列表框();
更新输入矩形();
//矩形变化时同步绑定的列表框
矩形改变后 += (x, y, w, h) => { 同步列表框(); 更新输入矩形(); };
}
public override void 初始化参数() {
文字 = nameof(下拉框);
格式 = 文字靠中;
字体 = 默认字体;
文字画笔 = 默认文字画笔;
阴影画笔 = 默认阴影画笔;
描边钢笔 = 默认描边钢笔;
鼠标离开时 += 文本框鼠标移开;
箭头样式 = 箭头样式.白色;
}
public override void 初始化事件() {
//当点击下拉箭头时
鼠标按下时 = (e) => {
if (矩形.Contains(e.x, e.y)) {
if (e.键位 == E键位.鼠标左键) {
更新输入矩形();
if (e.x > 箭头X) {
展开或关闭列表();
}
else {
//显示TextBox
if (已选中 == false && 已禁用 == false) {
已选中 = true;
显示TextBox(this);
}
else if (已选中 == true && 已禁用 == false) {
已选中 = false;
隐藏TextBox();
}
展开或关闭列表();
}
}
}
};
}
public void 加入面板(面板 面板) {
面板.添加(列表);
}
public int 箭头W { get { return 矩形.Height - 4; } }
protected int 箭头X { get { return 矩形.X + 矩形.Width - (矩形.Height - 4); } }
public new Rectangle 文字矩形 {
get {
return new Rectangle(X + 1, Y + 2, Math.Max(宽 / 2, 宽 - 2 - 按钮宽度 * 按钮文字.Count - 箭头W), 高 - 4);
}
}
public Rectangle 右边矩形 { get { return new Rectangle(箭头X, 矩形.Y + 2, 箭头W - 1, 箭头W - 1); } }
public Rectangle 下拉箭头矩形 {
get {
int XFix = (int)(箭头W * 图案缩小比例);
return new Rectangle(箭头X + XFix, 矩形.Y + 2 + XFix,
箭头W - 2 * XFix, 箭头W - 2 * XFix);
}
}
#region "文本框显示和隐藏"
/// <summary>当鼠标移出输入框后隐藏。</summary>
public override void 文本框鼠标移开(按键消息 e) {
if (鼠标移出后关闭列表) { 关闭列表(); 隐藏TextBox(false); }
else { 隐藏TextBox(false); }
}
/// <summary>更新输入框的矩形。</summary>
public override void 更新输入矩形() {
输入矩形.X = X - 1;
输入矩形.Y = Y - 高 + 1;
输入矩形.Width = 宽 + 2;
输入矩形.Height = Y - 输入矩形.Y + 1;
热区.MakeEmpty();
热区.Union(矩形);
热区.Union(输入矩形);
热区.Union(new Rectangle(列表.X, 列表.Y, 列表.宽, 显示行数 * 列表.格高));
}
#endregion
public void 同步列表框() {
if (列表 == null) { return; }
列表.矩形 = new Rectangle(X, Y + 高, 宽, 显示行数 * 列表.格高);
列表.格宽 = 列表.宽 / 列表.列数;
if (列表.面板 == null) {
if (面板 != null) { 面板.添加(列表); }
}
}
protected void 计算列表高() {
列表.高 = 显示行数 * 列表.格高 * Math.Abs(展开状态) / 1000;
}
public virtual void 展开或关闭列表() {
if (展开状态 == 0) {
列表.可见 = true;
展开状态 = 1;
} else if (展开状态 == 1000) {
展开状态 = -1000;
}
}
public virtual void 关闭列表() {
已选中 = false;
展开状态 = 0;
列表.可见 = false;
}
public override void 绘制(画家 画家) {
if (可见) {
if (展开状态 > 0 && 展开状态 < 1000) {
展开状态 = 展开状态 + 展开速度;
if (展开状态 >= 1000) { 展开状态 = 1000; }
计算列表高();
}
else if (展开状态 < 0) {
展开状态 = 展开状态 + 展开速度;
if (展开状态 >= 0) { 展开状态 = 0; 列表.可见 = false; }
计算列表高();
}
绘制底纹(画家);
绘制文字内容(画家);
绘制箭头(画家);
绘制边框(画家);
}
//DEBUG
//string str = string.Format("{0},{1},{2}",
// 面板.鼠标X, 面板.鼠标Y,点在控件中(面板.鼠标X, 面板.鼠标Y));
//画家.绘制漂浮文字描边(str, 500, 50, 默认字体, 默认文字画笔.资源, 默认描边钢笔.资源);
//画家.填充区域(默认透明画笔.资源, 热区);
}
public virtual void 绘制文字内容(画家 画家) {
if (背景色.A != 0) {
var Brush = new SolidBrush(背景色);
画家.填充矩形(Brush, 文字矩形);
Brush.Dispose();
}
绘制文字(文字, 画家, 文字矩形, true);
}
public virtual void 绘制箭头(画家 画家) {
画家.绘制矩形(箭头样式.钢笔.资源, 右边矩形);
画家.填充矩形(箭头样式.背景画笔.资源, 右边矩形);
画家.填充三角箭头(箭头样式.画笔.资源, 下拉箭头矩形, E方向.下);
}
}
}
下拉后的选项还有子选项的,子选项也可能出现子选项
要么找第三方控件,据我所知是没有的。
要么自己写,这个超级麻烦。
要么不用下拉框,让用户点击后弹出一个新窗口,新窗口里面弄多组选择框来选。